@@ -2674,41 +2674,10 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
26742674Instruction *InstCombinerImpl::foldICmpSRemConstant (ICmpInst &Cmp,
26752675 BinaryOperator *SRem,
26762676 const APInt &C) {
2677- const ICmpInst::Predicate Pred = Cmp.getPredicate ();
2678- if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT) {
2679- // Canonicalize unsigned predicates to signed:
2680- // (X s% DivisorC) u> C -> (X s% DivisorC) s< 0
2681- // iff (C s< 0 ? ~C : C) u>= abs(DivisorC)-1
2682- // (X s% DivisorC) u< C+1 -> (X s% DivisorC) s> -1
2683- // iff (C+1 s< 0 ? ~C : C) u>= abs(DivisorC)-1
2684-
2685- const APInt *DivisorC;
2686- if (!match (SRem->getOperand (1 ), m_APInt (DivisorC)))
2687- return nullptr ;
2688-
2689- APInt NormalizedC = C;
2690- if (Pred == ICmpInst::ICMP_ULT) {
2691- assert (!NormalizedC.isZero () &&
2692- " ult X, 0 should have been simplified already." );
2693- --NormalizedC;
2694- }
2695- if (C.isNegative ())
2696- NormalizedC.flipAllBits ();
2697- assert (!DivisorC->isZero () &&
2698- " srem X, 0 should have been simplified already." );
2699- if (!NormalizedC.uge (DivisorC->abs () - 1 ))
2700- return nullptr ;
2701-
2702- Type *Ty = SRem->getType ();
2703- if (Pred == ICmpInst::ICMP_UGT)
2704- return new ICmpInst (ICmpInst::ICMP_SLT, SRem,
2705- ConstantInt::getNullValue (Ty));
2706- return new ICmpInst (ICmpInst::ICMP_SGT, SRem,
2707- ConstantInt::getAllOnesValue (Ty));
2708- }
27092677 // Match an 'is positive' or 'is negative' comparison of remainder by a
27102678 // constant power-of-2 value:
27112679 // (X % pow2C) sgt/slt 0
2680+ const ICmpInst::Predicate Pred = Cmp.getPredicate ();
27122681 if (Pred != ICmpInst::ICMP_SGT && Pred != ICmpInst::ICMP_SLT &&
27132682 Pred != ICmpInst::ICMP_EQ && Pred != ICmpInst::ICMP_NE)
27142683 return nullptr ;
@@ -3164,7 +3133,9 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
31643133
31653134 if (ICmpInst::isUnsigned (Pred) && Add->hasNoSignedWrap () &&
31663135 C.isNonNegative () && (C - *C2).isNonNegative () &&
3167- computeConstantRange (X, /* ForSigned=*/ true ).add (*C2).isAllNonNegative ())
3136+ computeConstantRange (X, Add, /* ForSigned=*/ true )
3137+ .add (*C2)
3138+ .isAllNonNegative ())
31683139 return new ICmpInst (ICmpInst::getSignedPredicate (Pred), X,
31693140 ConstantInt::get (Ty, C - *C2));
31703141
@@ -7056,6 +7027,66 @@ static Instruction *canonicalizeICmpBool(ICmpInst &I,
70567027 }
70577028}
70587029
7030+ // (icmp X, Y) --> (icmp slt/sgt X, 0/-1) iff Y is outside the signed range of X
7031+ static ICmpInst *canonicalizeSignBitCheck (ICmpInst::Predicate Pred, Value *X,
7032+ const ConstantRange &XRange,
7033+ const ConstantRange &YRange) {
7034+ if (XRange.isSignWrappedSet ())
7035+ return nullptr ;
7036+ unsigned BitWidth = XRange.getBitWidth ();
7037+ APInt SMin = APInt::getSignedMinValue (BitWidth);
7038+ APInt Zero = APInt::getZero (BitWidth);
7039+ auto NegResult =
7040+ XRange.intersectWith (ConstantRange (SMin, Zero), ConstantRange::Signed)
7041+ .icmpOrInverse (Pred, YRange);
7042+ if (!NegResult)
7043+ return nullptr ;
7044+ auto PosResult =
7045+ XRange.intersectWith (ConstantRange (Zero, SMin), ConstantRange::Signed)
7046+ .icmpOrInverse (Pred, YRange);
7047+ if (!PosResult)
7048+ return nullptr ;
7049+ assert (NegResult != PosResult &&
7050+ " Known result should been simplified already." );
7051+ Type *Ty = X->getType ();
7052+ if (*NegResult)
7053+ return new ICmpInst (ICmpInst::ICMP_SLT, X, ConstantInt::getNullValue (Ty));
7054+ return new ICmpInst (ICmpInst::ICMP_SGT, X, ConstantInt::getAllOnesValue (Ty));
7055+ }
7056+
7057+ // Try to fold an icmp using the constant ranges of its operands.
7058+ Instruction *InstCombinerImpl::foldICmpUsingConstantRanges (ICmpInst &Cmp) {
7059+ Value *X = Cmp.getOperand (0 );
7060+ if (!X->getType ()->isIntOrIntVectorTy ())
7061+ return nullptr ;
7062+ Value *Y = Cmp.getOperand (1 );
7063+ ICmpInst::Predicate Pred = Cmp.getPredicate ();
7064+ ConstantRange XRange =
7065+ computeConstantRange (X, &Cmp, ICmpInst::isSigned (Pred));
7066+ if (XRange.isFullSet ())
7067+ return nullptr ; // early out if we don't have any information
7068+ ConstantRange YRange =
7069+ computeConstantRange (Y, &Cmp, ICmpInst::isSigned (Pred));
7070+ if (YRange.isFullSet ())
7071+ return nullptr ; // early out if we don't have any information
7072+ if (auto Res = XRange.icmpOrInverse (Pred, YRange))
7073+ return replaceInstUsesWith (Cmp, ConstantInt::getBool (Cmp.getType (), *Res));
7074+ if (ICmpInst::isUnsigned (Pred)) {
7075+ // Check if this icmp is actually a sign bit check.
7076+ const APInt *C;
7077+ bool IgnoreTrueIfSigned;
7078+ if (!match (Y, m_APInt (C)) ||
7079+ !isSignBitCheck (Pred, *C, IgnoreTrueIfSigned)) {
7080+ if (ICmpInst *Res = canonicalizeSignBitCheck (Pred, X, XRange, YRange))
7081+ return Res;
7082+ if (ICmpInst *Res = canonicalizeSignBitCheck (
7083+ ICmpInst::getSwappedPredicate (Pred), Y, YRange, XRange))
7084+ return Res;
7085+ }
7086+ }
7087+ return nullptr ;
7088+ }
7089+
70597090// Transform pattern like:
70607091// (1 << Y) u<= X or ~(-1 << Y) u< X or ((1 << Y)+(-1)) u< X
70617092// (1 << Y) u> X or ~(-1 << Y) u>= X or ((1 << Y)+(-1)) u>= X
@@ -7428,6 +7459,9 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
74287459 if (Instruction *Res = canonicalizeICmpPredicate (I))
74297460 return Res;
74307461
7462+ if (Instruction *Res = foldICmpUsingConstantRanges (I))
7463+ return Res;
7464+
74317465 if (Instruction *Res = foldICmpWithConstant (I))
74327466 return Res;
74337467
0 commit comments