@@ -1320,74 +1320,49 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
13201320Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges (ICmpInst *ICmp1,
13211321 ICmpInst *ICmp2,
13221322 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+ auto MatchRangeCheck =
1324+ [](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {
1325+ const APInt *C;
1326+ if (!match (ICmp->getOperand (1 ), m_APInt (C)))
1327+ return std::nullopt ;
1328+ Value *LHS = ICmp->getOperand (0 );
1329+ CmpPredicate Pred = ICmp->getPredicate ();
13551330 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;
1361- }
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;
1331+ // Match (x & NegPow2) ==/!= C
1332+ const APInt *Mask;
1333+ if (ICmpInst::isEquality (Pred) &&
1334+ match (LHS, m_OneUse (m_And (m_Value (X), m_NegatedPower2 (Mask)))) &&
1335+ C->countr_zero () >= Mask->countr_zero ()) {
1336+ ConstantRange CR{*C, *C - *Mask};
1337+ if (Pred == ICmpInst::ICMP_NE)
1338+ CR = CR.inverse ();
1339+ return std::make_pair (X, CR);
13671340 }
1368- }
1341+ ConstantRange CR = ConstantRange::makeExactICmpRegion (Pred, *C);
1342+ // Match (add X, C1) pred C
1343+ const APInt *C1;
1344+ if (match (LHS, m_AddLike (m_Value (X), m_APInt (C1))))
1345+ return std::make_pair (X, CR.subtract (*C1));
1346+ return std::make_pair (LHS, CR);
1347+ };
1348+
1349+ auto RC1 = MatchRangeCheck (ICmp1);
1350+ if (!RC1)
1351+ return nullptr ;
13691352
1370- if (V1 != V2)
1353+ auto RC2 = MatchRangeCheck (ICmp2);
1354+ if (!RC2)
13711355 return nullptr ;
13721356
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);
1388-
1389- Type *Ty = V1->getType ();
1390- Value *NewV = V1;
1357+ if (RC1->first != RC2->first )
1358+ return nullptr ;
1359+
1360+ Value *V = RC1->first ;
1361+ auto CR1 = IsAnd ? RC1->second .inverse () : RC1->second ;
1362+ auto CR2 = IsAnd ? RC2->second .inverse () : RC2->second ;
1363+
1364+ Type *Ty = V->getType ();
1365+ Value *NewV = V;
13911366 std::optional<ConstantRange> CR = CR1.exactUnionWith (CR2);
13921367 if (!CR) {
13931368 if (!(ICmp1->hasOneUse () && ICmp2->hasOneUse ()) || CR1.isWrappedSet () ||
0 commit comments