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 @@ -1480,10 +1480,11 @@ else return nullptr; - // X < Y && Y != 0 --> X < Y - // X < Y || Y != 0 --> Y != 0 - if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_NE) - return IsAnd ? UnsignedICmp : ZeroICmp; + // X > Y && Y == 0 --> Y == 0 iff X != 0 + // X > Y || Y == 0 --> X > Y iff X != 0 + if (UnsignedPred == ICmpInst::ICMP_UGT && EqPred == ICmpInst::ICMP_EQ && + isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + return IsAnd ? ZeroICmp : UnsignedICmp; // X <= Y && Y != 0 --> X <= Y iff X != 0 // X <= Y || Y != 0 --> Y != 0 iff X != 0 @@ -1491,17 +1492,21 @@ isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) return IsAnd ? UnsignedICmp : ZeroICmp; + // The transforms below here are expected to be handled more generally with + // simplifyAndOrOfICmpsWithLimitConst() or in InstCombine's + // foldAndOrOfICmpsWithConstEq(). If we are looking to trim optimizer overlap, + // these are candidates for removal. + + // X < Y && Y != 0 --> X < Y + // X < Y || Y != 0 --> Y != 0 + if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_NE) + return IsAnd ? UnsignedICmp : ZeroICmp; + // X >= Y && Y == 0 --> Y == 0 // X >= Y || Y == 0 --> X >= Y if (UnsignedPred == ICmpInst::ICMP_UGE && EqPred == ICmpInst::ICMP_EQ) return IsAnd ? ZeroICmp : UnsignedICmp; - // X > Y && Y == 0 --> Y == 0 iff X != 0 - // X > Y || Y == 0 --> X > Y iff X != 0 - if (UnsignedPred == ICmpInst::ICMP_UGT && EqPred == ICmpInst::ICMP_EQ && - isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) - return IsAnd ? ZeroICmp : UnsignedICmp; - // X < Y && Y == 0 --> false if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_EQ && IsAnd) @@ -1690,6 +1695,64 @@ return nullptr; } +/// Try to eliminate compares with signed or unsigned min/max constants. +static Value *simplifyAndOrOfICmpsWithLimitConst(ICmpInst *Cmp0, ICmpInst *Cmp1, + bool IsAnd) { + // Canonicalize an equality compare as Cmp0. + if (Cmp1->isEquality()) + std::swap(Cmp0, Cmp1); + if (!Cmp0->isEquality()) + return nullptr; + + // The equality compare must be against a constant. Convert the 'null' pointer + // constant to an integer zero value. + APInt MinMaxC; + const APInt *C; + if (match(Cmp0->getOperand(1), m_APInt(C))) + MinMaxC = *C; + else if (isa(Cmp0->getOperand(1))) + MinMaxC = APInt::getNullValue(8); + else + return nullptr; + + // The non-equality compare must include a common operand (X). Canonicalize + // the common operand as operand 0 (the predicate is swapped if the common + // operand was operand 1). + ICmpInst::Predicate Pred0 = Cmp0->getPredicate(); + Value *X = Cmp0->getOperand(0); + ICmpInst::Predicate Pred1; + if (!match(Cmp1, m_c_ICmp(Pred1, m_Specific(X), m_Value())) || + ICmpInst::isEquality(Pred1)) + return nullptr; + + // DeMorganize if this is 'or': P0 || P1 --> !P0 && !P1. + if (!IsAnd) { + Pred0 = ICmpInst::getInversePredicate(Pred0); + Pred1 = ICmpInst::getInversePredicate(Pred1); + } + + // Normalize to unsigned compare and unsigned min/max value. + // Example for 8-bit: -128 + 128 -> 0; 127 + 128 -> 255 + if (ICmpInst::isSigned(Pred1)) { + Pred1 = ICmpInst::getUnsignedPredicate(Pred1); + MinMaxC += APInt::getSignedMinValue(MinMaxC.getBitWidth()); + } + + // (X != MAX) && (X < Y) --> X < Y + // (X == MAX) || (X >= Y) --> X >= Y + if (MinMaxC.isMaxValue()) + if (Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_ULT) + return Cmp1; + + // (X != MIN) && (X > Y) --> X > Y + // (X == MIN) || (X <= Y) --> X <= Y + if (MinMaxC.isMinValue()) + if (Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_UGT) + return Cmp1; + + return nullptr; +} + static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1, const SimplifyQuery &Q) { if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true, Q)) @@ -1705,6 +1768,9 @@ if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true)) return X; + if (Value *X = simplifyAndOrOfICmpsWithLimitConst(Op0, Op1, true)) + return X; + if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, true)) return X; @@ -1778,6 +1844,9 @@ if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false)) return X; + if (Value *X = simplifyAndOrOfICmpsWithLimitConst(Op0, Op1, false)) + return X; + if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, false)) return X; diff --git a/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll b/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll @@ -644,9 +644,7 @@ define i1 @sge_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -657,9 +655,7 @@ define i1 @sge_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -670,9 +666,7 @@ define i1 @sge_swap_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -683,9 +677,7 @@ define i1 @sge_swap_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -696,9 +688,7 @@ define i1 @uge_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -709,9 +699,7 @@ define i1 @uge_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -722,9 +710,7 @@ define i1 @uge_swap_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -735,9 +721,7 @@ define i1 @uge_swap_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -754,9 +738,7 @@ define i1 @sle_or_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -767,9 +749,7 @@ define i1 @sle_or_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -780,9 +760,7 @@ define i1 @sle_swap_or_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -793,9 +771,7 @@ define i1 @sle_swap_or_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -856,9 +832,7 @@ define i1 @slt_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -869,9 +843,7 @@ define i1 @slt_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -882,9 +854,7 @@ define i1 @slt_swap_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -895,9 +865,7 @@ define i1 @slt_swap_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -908,9 +876,7 @@ define i1 @ult_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -921,9 +887,7 @@ define i1 @ult_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -934,9 +898,7 @@ define i1 @ult_swap_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -947,9 +909,7 @@ define i1 @ult_swap_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -966,9 +926,7 @@ define i1 @sgt_and_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_and_not_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -979,9 +937,7 @@ define i1 @sgt_and_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_and_not_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -992,9 +948,7 @@ define i1 @sgt_swap_and_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_not_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 @@ -1005,9 +959,7 @@ define i1 @sgt_swap_and_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_not_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 diff --git a/llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll b/llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll --- a/llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll +++ b/llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll @@ -644,9 +644,7 @@ define i1 @sge_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -657,9 +655,7 @@ define i1 @sge_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -670,9 +666,7 @@ define i1 @sge_swap_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -683,9 +677,7 @@ define i1 @sge_swap_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -696,9 +688,7 @@ define i1 @uge_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -709,9 +699,7 @@ define i1 @uge_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -722,9 +710,7 @@ define i1 @uge_swap_or_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -735,9 +721,7 @@ define i1 @uge_swap_or_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -754,9 +738,7 @@ define i1 @sle_or_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -767,9 +749,7 @@ define i1 @sle_or_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -780,9 +760,7 @@ define i1 @sle_swap_or_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -793,9 +771,7 @@ define i1 @sle_swap_or_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -856,9 +832,7 @@ define i1 @slt_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -869,9 +843,7 @@ define i1 @slt_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -882,9 +854,7 @@ define i1 @slt_swap_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -895,9 +865,7 @@ define i1 @slt_swap_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -908,9 +876,7 @@ define i1 @ult_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -921,9 +887,7 @@ define i1 @ult_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -934,9 +898,7 @@ define i1 @ult_swap_and_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_not_max( ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -947,9 +909,7 @@ define i1 @ult_swap_and_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_not_max_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -966,9 +926,7 @@ define i1 @sgt_and_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_and_not_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -979,9 +937,7 @@ define i1 @sgt_and_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_and_not_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -992,9 +948,7 @@ define i1 @sgt_swap_and_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_not_min( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 @@ -1005,9 +959,7 @@ define i1 @sgt_swap_and_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_not_min_commute( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 diff --git a/llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll b/llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll --- a/llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll +++ b/llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll @@ -56,6 +56,21 @@ ret i1 %r } +; Negative test - signed compare + +define i1 @sgt_and_min(i9* %x, i9* %y) { +; CHECK-LABEL: @sgt_and_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i9* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i9* [[X]], null +; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sgt i9* %x, %y + %cmpeq = icmp eq i9* %x, null + %r = and i1 %cmp, %cmpeq + ret i1 %r +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; (X != null) || (X <= Y) --> true @@ -102,6 +117,21 @@ ret i1 %r } +; Negative test - signed compare + +define i1 @sle_or_not_min(i427* %x, i427* %y) { +; CHECK-LABEL: @sle_or_not_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i427* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i427* [[X]], null +; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sle i427* %x, %y + %cmpeq = icmp ne i427* %x, null + %r = or i1 %cmp, %cmpeq + ret i1 %r +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; (X == null) && (X <= Y) --> X == null @@ -152,6 +182,21 @@ ret i1 %r } +; Negative test - signed compare + +define i1 @sle_and_min(i8* %x, i8* %y) { +; CHECK-LABEL: @sle_and_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8* [[X]], null +; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sle i8* %x, %y + %cmpeq = icmp eq i8* %x, null + %r = and i1 %cmp, %cmpeq + ret i1 %r +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; (X == null) || (X <= Y) --> X <= Y @@ -202,6 +247,21 @@ ret i1 %r } +; Negative test - signed compare + +define i1 @sle_or_min(i8* %x, i8* %y) { +; CHECK-LABEL: @sle_or_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8* [[X]], null +; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sle i8* %x, %y + %cmpeq = icmp eq i8* %x, null + %r = or i1 %cmp, %cmpeq + ret i1 %r +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; (X != null) && (X > Y) --> X > Y @@ -252,6 +312,21 @@ ret i1 %r } +; Negative test - signed compare + +define i1 @sgt_and_not_min(i8* %x, i8* %y) { +; CHECK-LABEL: @sgt_and_not_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8* [[X]], null +; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sgt i8* %x, %y + %cmpeq = icmp ne i8* %x, null + %r = and i1 %cmp, %cmpeq + ret i1 %r +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; (X != null) || (X > Y) --> X != null @@ -301,3 +376,18 @@ %r = or i1 %cmpeq, %cmp ret i1 %r } + +; Negative test - signed compare + +define i1 @sgt_or_not_min(i8* %x, i8* %y) { +; CHECK-LABEL: @sgt_or_not_min( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8* [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8* [[X]], null +; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp = icmp sgt i8* %x, %y + %cmpeq = icmp ne i8* %x, null + %r = or i1 %cmp, %cmpeq + ret i1 %r +}