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,8 +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. Cases not handled here - // require a 'not' of the LHS, so those must be transformed in InstCombine. + // (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; + } + if (match(RHS, m_Zero())) { switch (Pred) { case CmpInst::ICMP_NE: // X != 0 -> X 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,6 +186,72 @@ ret i1 %cmp } +; 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 + %t0 = sext i1 %not to i32 + %cmp = icmp eq i32 %t0, 0 + ret i1 %cmp +} + ; Don't crash matching recurrences/invertible ops. define void @PR50191(i32 %x) {