@@ -1172,7 +1172,7 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
1172
1172
static Value *foldAndOrOfICmpsUsingRanges (
1173
1173
ICmpInst::Predicate Pred1, Value *V1, const APInt &C1,
1174
1174
ICmpInst::Predicate Pred2, Value *V2, const APInt &C2,
1175
- IRBuilderBase &Builder, bool IsAnd) {
1175
+ IRBuilderBase &Builder, bool IsAnd, bool BothHaveOneUse ) {
1176
1176
// Look through add of a constant offset on V1, V2, or both operands. This
1177
1177
// allows us to interpret the V + C' < C'' range idiom into a proper range.
1178
1178
const APInt *Offset1 = nullptr , *Offset2 = nullptr ;
@@ -1195,17 +1195,35 @@ static Value *foldAndOrOfICmpsUsingRanges(
1195
1195
if (Offset2)
1196
1196
CR2 = CR2.subtract (*Offset2);
1197
1197
1198
+ Type *Ty = V1->getType ();
1199
+ Value *NewV = V1;
1198
1200
Optional<ConstantRange> CR =
1199
1201
IsAnd ? CR1.exactIntersectWith (CR2) : CR1.exactUnionWith (CR2);
1200
- if (!CR)
1201
- return nullptr ;
1202
+ if (!CR) {
1203
+ // TODO: Support and.
1204
+ if (IsAnd)
1205
+ return nullptr ;
1206
+
1207
+ if (!BothHaveOneUse || CR1.isWrappedSet () || CR2.isWrappedSet ())
1208
+ return nullptr ;
1209
+
1210
+ // Check whether we have equal-size ranges that only differ by one bit.
1211
+ // In that case we can apply a mask to map one range onto the other.
1212
+ APInt LowerDiff = CR1.getLower () ^ CR2.getLower ();
1213
+ APInt UpperDiff = (CR1.getUpper () - 1 ) ^ (CR2.getUpper () - 1 );
1214
+ APInt CR1Size = CR1.getUpper () - CR1.getLower ();
1215
+ if (!LowerDiff.isPowerOf2 () || LowerDiff != UpperDiff ||
1216
+ CR1Size != CR2.getUpper () - CR2.getLower ())
1217
+ return nullptr ;
1218
+
1219
+ CR = CR1.getLower ().ult (CR2.getLower ()) ? CR1 : CR2;
1220
+ NewV = Builder.CreateAnd (NewV, ConstantInt::get (Ty, ~LowerDiff));
1221
+ }
1202
1222
1203
1223
CmpInst::Predicate NewPred;
1204
1224
APInt NewC, Offset;
1205
1225
CR->getEquivalentICmp (NewPred, NewC, Offset);
1206
1226
1207
- Type *Ty = V1->getType ();
1208
- Value *NewV = V1;
1209
1227
if (Offset != 0 )
1210
1228
NewV = Builder.CreateAdd (NewV, ConstantInt::get (Ty, Offset));
1211
1229
return Builder.CreateICmp (NewPred, NewV, ConstantInt::get (Ty, NewC));
@@ -2418,58 +2436,6 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
2418
2436
match (LHS1, m_APInt (LHSC));
2419
2437
match (RHS1, m_APInt (RHSC));
2420
2438
2421
- // Fold (icmp ult/ule (A + C1), C3) | (icmp ult/ule (A + C2), C3)
2422
- // --> (icmp ult/ule ((A & ~(C1 ^ C2)) + max(C1, C2)), C3)
2423
- // The original condition actually refers to the following two ranges:
2424
- // [MAX_UINT-C1+1, MAX_UINT-C1+1+C3] and [MAX_UINT-C2+1, MAX_UINT-C2+1+C3]
2425
- // We can fold these two ranges if:
2426
- // 1) C1 and C2 is unsigned greater than C3.
2427
- // 2) The two ranges are separated.
2428
- // 3) C1 ^ C2 is one-bit mask.
2429
- // 4) LowRange1 ^ LowRange2 and HighRange1 ^ HighRange2 are one-bit mask.
2430
- // This implies all values in the two ranges differ by exactly one bit.
2431
- if (!IsAnd && (PredL == ICmpInst::ICMP_ULT || PredL == ICmpInst::ICMP_ULE) &&
2432
- PredL == PredR && LHSC && RHSC && LHS->hasOneUse () && RHS->hasOneUse () &&
2433
- LHSC->getBitWidth () == RHSC->getBitWidth () && *LHSC == *RHSC) {
2434
-
2435
- Value *AddOpnd;
2436
- const APInt *LAddC, *RAddC;
2437
- if (match (LHS0, m_Add (m_Value (AddOpnd), m_APInt (LAddC))) &&
2438
- match (RHS0, m_Add (m_Specific (AddOpnd), m_APInt (RAddC))) &&
2439
- LAddC->ugt (*LHSC) && RAddC->ugt (*LHSC)) {
2440
-
2441
- APInt DiffC = *LAddC ^ *RAddC;
2442
- if (DiffC.isPowerOf2 ()) {
2443
- const APInt *MaxAddC = nullptr ;
2444
- if (LAddC->ult (*RAddC))
2445
- MaxAddC = RAddC;
2446
- else
2447
- MaxAddC = LAddC;
2448
-
2449
- APInt RRangeLow = -*RAddC;
2450
- APInt RRangeHigh = RRangeLow + *LHSC;
2451
- APInt LRangeLow = -*LAddC;
2452
- APInt LRangeHigh = LRangeLow + *LHSC;
2453
- APInt LowRangeDiff = RRangeLow ^ LRangeLow;
2454
- APInt HighRangeDiff = RRangeHigh ^ LRangeHigh;
2455
- APInt RangeDiff = LRangeLow.sgt (RRangeLow) ? LRangeLow - RRangeLow
2456
- : RRangeLow - LRangeLow;
2457
-
2458
- if (LowRangeDiff.isPowerOf2 () && LowRangeDiff == HighRangeDiff &&
2459
- RangeDiff.ugt (*LHSC)) {
2460
- Type *Ty = AddOpnd->getType ();
2461
- Value *MaskC = ConstantInt::get (Ty, ~DiffC);
2462
-
2463
- Value *NewAnd = Builder.CreateAnd (AddOpnd, MaskC);
2464
- Value *NewAdd = Builder.CreateAdd (NewAnd,
2465
- ConstantInt::get (Ty, *MaxAddC));
2466
- return Builder.CreateICmp (LHS->getPredicate (), NewAdd,
2467
- ConstantInt::get (Ty, *LHSC));
2468
- }
2469
- }
2470
- }
2471
- }
2472
-
2473
2439
// (icmp1 A, B) | (icmp2 A, B) --> (icmp3 A, B)
2474
2440
// (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B)
2475
2441
if (predicatesFoldable (PredL, PredR)) {
@@ -2586,7 +2552,8 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
2586
2552
}
2587
2553
2588
2554
return foldAndOrOfICmpsUsingRanges (PredL, LHS0, *LHSC, PredR, RHS0, *RHSC,
2589
- Builder, IsAnd);
2555
+ Builder, IsAnd,
2556
+ LHS->hasOneUse () && RHS->hasOneUse ());
2590
2557
}
2591
2558
2592
2559
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
0 commit comments