@@ -2674,41 +2674,10 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
2674
2674
Instruction *InstCombinerImpl::foldICmpSRemConstant(ICmpInst &Cmp,
2675
2675
BinaryOperator *SRem,
2676
2676
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
- }
2709
2677
// Match an 'is positive' or 'is negative' comparison of remainder by a
2710
2678
// constant power-of-2 value:
2711
2679
// (X % pow2C) sgt/slt 0
2680
+ const ICmpInst::Predicate Pred = Cmp.getPredicate();
2712
2681
if (Pred != ICmpInst::ICMP_SGT && Pred != ICmpInst::ICMP_SLT &&
2713
2682
Pred != ICmpInst::ICMP_EQ && Pred != ICmpInst::ICMP_NE)
2714
2683
return nullptr;
@@ -3164,7 +3133,10 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
3164
3133
3165
3134
if (ICmpInst::isUnsigned(Pred) && Add->hasNoSignedWrap() &&
3166
3135
C.isNonNegative() && (C - *C2).isNonNegative() &&
3167
- computeConstantRange(X, /*ForSigned=*/true).add(*C2).isAllNonNegative())
3136
+ computeConstantRange(X, /*ForSigned=*/true, /*UseInstrInfo=*/true, &AC,
3137
+ Add, &DT)
3138
+ .add(*C2)
3139
+ .isAllNonNegative())
3168
3140
return new ICmpInst(ICmpInst::getSignedPredicate(Pred), X,
3169
3141
ConstantInt::get(Ty, C - *C2));
3170
3142
@@ -7056,6 +7028,66 @@ static Instruction *canonicalizeICmpBool(ICmpInst &I,
7056
7028
}
7057
7029
}
7058
7030
7031
+ // (icmp X, Y) --> (icmp slt/sgt X, 0/-1) iff Y is outside the signed range of X
7032
+ static ICmpInst *canonicalizeSignBitCheck(ICmpInst::Predicate Pred, Value *X,
7033
+ const ConstantRange &XRange,
7034
+ const ConstantRange &YRange) {
7035
+ if (XRange.isSignWrappedSet())
7036
+ return nullptr;
7037
+ unsigned BitWidth = XRange.getBitWidth();
7038
+ APInt SMin = APInt::getSignedMinValue(BitWidth);
7039
+ APInt Zero = APInt::getZero(BitWidth);
7040
+ auto NegResult =
7041
+ XRange.intersectWith(ConstantRange(SMin, Zero), ConstantRange::Signed)
7042
+ .icmpOrInverse(Pred, YRange);
7043
+ if (!NegResult)
7044
+ return nullptr;
7045
+ auto PosResult =
7046
+ XRange.intersectWith(ConstantRange(Zero, SMin), ConstantRange::Signed)
7047
+ .icmpOrInverse(Pred, YRange);
7048
+ if (!PosResult)
7049
+ return nullptr;
7050
+ assert(NegResult != PosResult &&
7051
+ "Known result should been simplified already.");
7052
+ Type *Ty = X->getType();
7053
+ if (*NegResult)
7054
+ return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::getNullValue(Ty));
7055
+ return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantInt::getAllOnesValue(Ty));
7056
+ }
7057
+
7058
+ // Try to fold an icmp using the constant ranges of its operands.
7059
+ Instruction *InstCombinerImpl::foldICmpUsingConstantRanges(ICmpInst &Cmp) {
7060
+ Value *X = Cmp.getOperand(0);
7061
+ if (!X->getType()->isIntOrIntVectorTy())
7062
+ return nullptr;
7063
+ Value *Y = Cmp.getOperand(1);
7064
+ ICmpInst::Predicate Pred = Cmp.getPredicate();
7065
+ ConstantRange XRange = computeConstantRange(
7066
+ X, ICmpInst::isSigned(Pred), /*UseInstrInfo=*/true, &AC, &Cmp, &DT);
7067
+ if (XRange.isFullSet())
7068
+ return nullptr; // early out if we don't have any information
7069
+ ConstantRange YRange = computeConstantRange(
7070
+ Y, ICmpInst::isSigned(Pred), /*UseInstrInfo=*/true, &AC, &Cmp, &DT);
7071
+ if (YRange.isFullSet())
7072
+ return nullptr; // early out if we don't have any information
7073
+ if (auto Res = XRange.icmpOrInverse(Pred, YRange))
7074
+ return replaceInstUsesWith(Cmp, ConstantInt::getBool(Cmp.getType(), *Res));
7075
+ if (ICmpInst::isUnsigned(Pred)) {
7076
+ // Check if this icmp is actually a sign bit check.
7077
+ const APInt *C;
7078
+ bool IgnoreTrueIfSigned;
7079
+ if (!match(Y, m_APInt(C)) ||
7080
+ !isSignBitCheck(Pred, *C, IgnoreTrueIfSigned)) {
7081
+ if (ICmpInst *Res = canonicalizeSignBitCheck(Pred, X, XRange, YRange))
7082
+ return Res;
7083
+ if (ICmpInst *Res = canonicalizeSignBitCheck(
7084
+ ICmpInst::getSwappedPredicate(Pred), Y, YRange, XRange))
7085
+ return Res;
7086
+ }
7087
+ }
7088
+ return nullptr;
7089
+ }
7090
+
7059
7091
// Transform pattern like:
7060
7092
// (1 << Y) u<= X or ~(-1 << Y) u< X or ((1 << Y)+(-1)) u< X
7061
7093
// (1 << Y) u> X or ~(-1 << Y) u>= X or ((1 << Y)+(-1)) u>= X
@@ -7428,6 +7460,9 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
7428
7460
if (Instruction *Res = canonicalizeICmpPredicate(I))
7429
7461
return Res;
7430
7462
7463
+ if (Instruction *Res = foldICmpUsingConstantRanges(I))
7464
+ return Res;
7465
+
7431
7466
if (Instruction *Res = foldICmpWithConstant(I))
7432
7467
return Res;
7433
7468
0 commit comments