@@ -1320,71 +1320,52 @@ 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+   //  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 ();
13551331    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);
13611341    }
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 ;
13691358
1359+   auto  &[V1, CR1] = *RC1;
1360+   auto  &[V2, CR2] = *RC2;
13701361  if  (V1 != V2)
13711362    return  nullptr ;
13721363
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+   }
13881369
13891370  Type *Ty = V1->getType ();
13901371  Value *NewV = V1;
0 commit comments