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 @@ -2706,6 +2706,14 @@ // 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. + + auto ExtractNotLHS = [](Value *V) -> Value * { + Value *X; + if (match(V, m_Xor(m_Value(X), m_One()))) + return X; + return nullptr; + }; + if (match(RHS, m_Zero())) { switch (Pred) { case CmpInst::ICMP_NE: // X != 0 -> X @@ -2713,6 +2721,12 @@ case CmpInst::ICMP_SLT: // X X return LHS; + case CmpInst::ICMP_EQ: // not(X) == 0 -> X != 0 -> X + case CmpInst::ICMP_ULE: // not(X) <=u 0 -> X >u 0 -> X + case CmpInst::ICMP_SGE: // not(X) >=s 0 -> X X + if (Value *X = ExtractNotLHS(LHS)) + return X; + case CmpInst::ICMP_ULT: // X false case CmpInst::ICMP_SGT: // X >s 0 -> false return getFalse(ITy); @@ -2730,6 +2744,12 @@ case CmpInst::ICMP_SLE: // X <=s -1 -> X return LHS; + case CmpInst::ICMP_NE: // not(X) != 1 -> X == 1 -> X + case CmpInst::ICMP_ULT: // not(X) <=u 1 -> X >=u 1 -> X + case CmpInst::ICMP_SGT: // not(X) >s 1 -> X <=s -1 -> X + if (Value *X = ExtractNotLHS(LHS)) + return X; + case CmpInst::ICMP_UGT: // X >u 1 -> false case CmpInst::ICMP_SLT: // X false return getFalse(ITy); diff --git a/llvm/test/Transforms/InstSimplify/icmp-not-bool-constant.ll b/llvm/test/Transforms/InstSimplify/icmp-not-bool-constant.ll --- a/llvm/test/Transforms/InstSimplify/icmp-not-bool-constant.ll +++ b/llvm/test/Transforms/InstSimplify/icmp-not-bool-constant.ll @@ -17,9 +17,7 @@ define <2 x i1> @eq_f_not(<2 x i1> %a) { ; CHECK-LABEL: @eq_f_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i1> [[NOT]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp eq <2 x i1> %not, @@ -28,9 +26,7 @@ define <2 x i1> @ne_t_not(<2 x i1> %a) { ; CHECK-LABEL: @ne_t_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i1> [[NOT]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp ne <2 x i1> %not, @@ -68,9 +64,7 @@ define <2 x i1> @ult_t_not(<2 x i1> %a) { ; CHECK-LABEL: @ult_t_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i1> [[NOT]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp ult <2 x i1> %not, @@ -88,9 +82,7 @@ define <2 x i1> @sgt_t_not(<2 x i1> %a) { ; CHECK-LABEL: @sgt_t_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i1> [[NOT]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp sgt <2 x i1> %not, @@ -155,9 +147,7 @@ define <2 x i1> @ule_f_not(<2 x i1> %a) { ; CHECK-LABEL: @ule_f_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp ule <2 x i1> [[NOT]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp ule <2 x i1> %not, @@ -175,9 +165,7 @@ define <2 x i1> @sge_f_not(<2 x i1> %a) { ; CHECK-LABEL: @sge_f_not( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp sge <2 x i1> [[NOT]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[A:%.*]] ; %not = xor <2 x i1> %a, %r = icmp sge <2 x i1> %not,