@@ -1320,71 +1320,52 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
1320
1320
Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges (ICmpInst *ICmp1,
1321
1321
ICmpInst *ICmp2,
1322
1322
bool IsAnd) {
1323
- CmpPredicate Pred1, Pred2;
1324
- Value *V1, *V2;
1325
- const APInt *C1, *C2;
1326
- if (!match (ICmp1, m_ICmp (Pred1, m_Value (V1), m_APInt (C1))) ||
1327
- !match (ICmp2, m_ICmp (Pred2, m_Value (V2), m_APInt (C2))))
1328
- return nullptr ;
1329
-
1330
- // Look through add of a constant offset on V1, V2, or both operands. This
1331
- // allows us to interpret the V + C' < C'' range idiom into a proper range.
1332
- const APInt *Offset1 = nullptr , *Offset2 = nullptr ;
1333
- if (V1 != V2) {
1334
- Value *X;
1335
- if (match (V1, m_Add (m_Value (X), m_APInt (Offset1))))
1336
- V1 = X;
1337
- if (match (V2, m_Add (m_Value (X), m_APInt (Offset2))))
1338
- V2 = X;
1339
- }
1340
-
1341
- // Look through and with a negative power of 2 mask on V1 or V2. This
1342
- // detects idioms of the form `(x == A) || ((x & Mask) == A + 1)` where A + 1
1343
- // is aligned to the mask and A + 1 >= |Mask|. This pattern corresponds to a
1344
- // contiguous range check, which can be folded into an addition and compare.
1345
- // The same applies for `(x != A) && ((x & Mask) != A + 1)`.
1346
- auto AreContiguousRangePredicates = [](CmpPredicate Pred1, CmpPredicate Pred2,
1347
- bool IsAnd) {
1348
- if (IsAnd)
1349
- return Pred1 == ICmpInst::ICMP_NE && Pred2 == ICmpInst::ICMP_NE;
1350
- return Pred1 == ICmpInst::ICMP_EQ && Pred2 == ICmpInst::ICMP_EQ;
1351
- };
1352
- const APInt *Mask1 = nullptr , *Mask2 = nullptr ;
1353
- bool MatchedAnd1 = false , MatchedAnd2 = false ;
1354
- if (V1 != V2 && AreContiguousRangePredicates (Pred1, Pred2, IsAnd)) {
1323
+ // Return (V, CR) for a range check idiom V in CR.
1324
+ auto MatchExactRangeCheck =
1325
+ [](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {
1326
+ const APInt *C;
1327
+ if (!match (ICmp->getOperand (1 ), m_APInt (C)))
1328
+ return std::nullopt ;
1329
+ Value *LHS = ICmp->getOperand (0 );
1330
+ CmpPredicate Pred = ICmp->getPredicate ();
1355
1331
Value *X;
1356
- if (match (V1, m_OneUse (m_And (m_Value (X), m_NegatedPower2 (Mask1)))) &&
1357
- C1->getBitWidth () == C2->getBitWidth () && *C1 == *C2 + 1 &&
1358
- C1->uge (Mask1->abs ()) && C1->isPowerOf2 ()) {
1359
- MatchedAnd1 = true ;
1360
- V1 = X;
1332
+ // Match (x & NegPow2) ==/!= C
1333
+ const APInt *Mask;
1334
+ if (ICmpInst::isEquality (Pred) &&
1335
+ match (LHS, m_OneUse (m_And (m_Value (X), m_NegatedPower2 (Mask)))) &&
1336
+ C->countr_zero () >= Mask->countr_zero ()) {
1337
+ ConstantRange CR (*C, *C - *Mask);
1338
+ if (Pred == ICmpInst::ICMP_NE)
1339
+ CR = CR.inverse ();
1340
+ return std::make_pair (X, CR);
1361
1341
}
1362
- if (match (V2, m_OneUse (m_And (m_Value (X), m_NegatedPower2 (Mask2)))) &&
1363
- C1->getBitWidth () == C2->getBitWidth () && *C2 == *C1 + 1 &&
1364
- C2->uge (Mask2->abs ()) && C2->isPowerOf2 ()) {
1365
- MatchedAnd2 = true ;
1366
- V2 = X;
1367
- }
1368
- }
1342
+ ConstantRange CR = ConstantRange::makeExactICmpRegion (Pred, *C);
1343
+ // Match (add X, C1) pred C
1344
+ // TODO: investigate whether we should apply the one-use check on m_AddLike.
1345
+ const APInt *C1;
1346
+ if (match (LHS, m_AddLike (m_Value (X), m_APInt (C1))))
1347
+ return std::make_pair (X, CR.subtract (*C1));
1348
+ return std::make_pair (LHS, CR);
1349
+ };
1350
+
1351
+ auto RC1 = MatchExactRangeCheck (ICmp1);
1352
+ if (!RC1)
1353
+ return nullptr ;
1354
+
1355
+ auto RC2 = MatchExactRangeCheck (ICmp2);
1356
+ if (!RC2)
1357
+ return nullptr ;
1369
1358
1359
+ auto &[V1, CR1] = *RC1;
1360
+ auto &[V2, CR2] = *RC2;
1370
1361
if (V1 != V2)
1371
1362
return nullptr ;
1372
1363
1373
- ConstantRange CR1 =
1374
- MatchedAnd1
1375
- ? ConstantRange (*C1, *C1 - *Mask1)
1376
- : ConstantRange::makeExactICmpRegion (
1377
- IsAnd ? ICmpInst::getInverseCmpPredicate (Pred1) : Pred1, *C1);
1378
- if (Offset1)
1379
- CR1 = CR1.subtract (*Offset1);
1380
-
1381
- ConstantRange CR2 =
1382
- MatchedAnd2
1383
- ? ConstantRange (*C2, *C2 - *Mask2)
1384
- : ConstantRange::makeExactICmpRegion (
1385
- IsAnd ? ICmpInst::getInverseCmpPredicate (Pred2) : Pred2, *C2);
1386
- if (Offset2)
1387
- CR2 = CR2.subtract (*Offset2);
1364
+ // For 'and', we use the De Morgan's Laws to simplify the implementation.
1365
+ if (IsAnd) {
1366
+ CR1 = CR1.inverse ();
1367
+ CR2 = CR2.inverse ();
1368
+ }
1388
1369
1389
1370
Type *Ty = V1->getType ();
1390
1371
Value *NewV = V1;
0 commit comments