diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1337,6 +1337,19 @@ if (Instruction *Res = processUGT_ADDCST_ADD(Cmp, A, B, CI2, CI, *this)) return Res; + Value *X; + // icmp slt (and (sub 0, X), X), 0 --> icmp eq (X, CI) + // icmp sgt (and (sub 0, X), X), -1 --> icmp ne (X, CI) + if (match(Op0, m_OneUse(m_And(m_Sub(m_Zero(), m_Value(X)), m_Deferred(X))))) { + Constant *CI = ConstantInt::get( + X->getType(), + APInt::getSignedMinValue(X->getType()->getScalarSizeInBits())); + if (Pred == ICmpInst::ICMP_SLT && match(Op1, m_Zero())) + return new ICmpInst(ICmpInst::ICMP_EQ, X, CI); + if (Pred == ICmpInst::ICMP_SGT && match(Op1, m_AllOnes())) + return new ICmpInst(ICmpInst::ICMP_NE, X, CI); + } + // icmp(phi(C1, C2, ...), C) -> phi(icmp(C1, C), icmp(C2, C), ...). Constant *C = dyn_cast(Op1); if (!C) diff --git a/llvm/test/Transforms/InstCombine/fold-signbit-test-power2.ll b/llvm/test/Transforms/InstCombine/fold-signbit-test-power2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-signbit-test-power2.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s +define i1 @pow2_or_zero1(i8 %x) { +; CHECK-LABEL: @pow2_or_zero1( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMP]] +; + %negx = sub i8 0, %x + %pow2_or_zero = and i8 %negx, %x + %cmp = icmp slt i8 %pow2_or_zero, 0 + ret i1 %cmp +} + +define i1 @pow2_or_zero2(i8 %x) { +; CHECK-LABEL: @pow2_or_zero2( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMP]] +; + %negx = sub i8 0, %x + %pow2_or_zero = and i8 %negx, %x + %cmp = icmp sgt i8 %pow2_or_zero, -1 + ret i1 %cmp +} diff --git a/llvm/test/Transforms/InstCombine/minmax-of-xor-x.ll b/llvm/test/Transforms/InstCombine/minmax-of-xor-x.ll --- a/llvm/test/Transforms/InstCombine/minmax-of-xor-x.ll +++ b/llvm/test/Transforms/InstCombine/minmax-of-xor-x.ll @@ -134,9 +134,7 @@ define i8 @smax_xor_pow2_neg(i8 %x, i8 %y) { ; CHECK-LABEL: @smax_xor_pow2_neg( -; CHECK-NEXT: [[NY:%.*]] = sub i8 0, [[Y:%.*]] -; CHECK-NEXT: [[YP2:%.*]] = and i8 [[NY]], [[Y]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[YP2]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[Y:%.*]], -128 ; CHECK-NEXT: br i1 [[CMP]], label [[NEG:%.*]], label [[POS:%.*]] ; CHECK: neg: ; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 127