diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2705,11 +2705,16 @@ return nullptr; // A boolean compared to true/false can be simplified in 14 out of the 20 + // (10 predicates * 2 constants) possible combinations. + // If LHS is of the form not(X), inverse the predicate. + // E.g not(X) == 0 -> X != 0 Value *X; + if (match(LHS, m_Xor(m_Value(X), m_One()))) { + Pred = CmpInst::getInversePredicate(Pred); + LHS = X; + } - // (10 predicates * 2 constants) possible combinations. Cases not handled here - // require a 'not' of the LHS, so those must be transformed in InstCombine. if (match(RHS, m_Zero())) { switch (Pred) { case CmpInst::ICMP_NE: // X != 0 -> X @@ -2717,13 +2722,6 @@ case CmpInst::ICMP_SLT: // X X return LHS; - case CmpInst::ICMP_EQ: - // (X ^ 1) == 0 -> X - if (match(LHS, m_Xor(m_Value(X), m_One()))) { - return X; - } - break; - case CmpInst::ICMP_ULT: // X false case CmpInst::ICMP_SGT: // X >s 0 -> false return getFalse(ITy); diff --git a/llvm/test/Transforms/InstSimplify/icmp.ll b/llvm/test/Transforms/InstSimplify/icmp.ll --- a/llvm/test/Transforms/InstSimplify/icmp.ll +++ b/llvm/test/Transforms/InstSimplify/icmp.ll @@ -186,8 +186,64 @@ ret i1 %cmp } -define i1 @not_cmp_equal(i1 %x) { -; CHECK-LABEL: @not_cmp_equal( +; Test simplification with not in LHS + +define i1 @not_cmp_eq(i1 %x) { +; CHECK-LABEL: @not_cmp_eq( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp eq i1 %not, 0 + ret i1 %cmp +} + +define i1 @not_cmp_ule(i1 %x) { +; CHECK-LABEL: @not_cmp_ule( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp ule i1 %not, 0 + ret i1 %cmp +} + +define i1 @not_cmp_sge(i1 %x) { +; CHECK-LABEL: @not_cmp_sge( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp sge i1 %not, 0 + ret i1 %cmp +} + +define i1 @not_cmp_ne(i1 %x) { +; CHECK-LABEL: @not_cmp_ne( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp ne i1 %not, true + ret i1 %cmp +} + +define i1 @not_cmp_ult(i1 %x) { +; CHECK-LABEL: @not_cmp_ult( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp ult i1 %not, 1 + ret i1 %cmp +} + +define i1 @not_cmp_sgt(i1 %x) { +; CHECK-LABEL: @not_cmp_sgt( +; CHECK-NEXT: ret i1 %x +; + %not = xor i1 %x, true + %cmp = icmp sgt i1 %not, -1 + ret i1 %cmp +} + +define i1 @not_cmp_sext(i1 %x) { +; CHECK-LABEL: @not_cmp_sext( ; CHECK-NEXT: ret i1 %x ; %not = xor i1 %x, true