[llvm] [InstCombine] Generalize `foldAndOrOfICmpsUsingRanges` to handle more cases. (PR #158498)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 15 10:11:54 PDT 2025


================
@@ -1320,74 +1320,49 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
 Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
                                                      ICmpInst *ICmp2,
                                                      bool IsAnd) {
-  CmpPredicate Pred1, Pred2;
-  Value *V1, *V2;
-  const APInt *C1, *C2;
-  if (!match(ICmp1, m_ICmp(Pred1, m_Value(V1), m_APInt(C1))) ||
-      !match(ICmp2, m_ICmp(Pred2, m_Value(V2), m_APInt(C2))))
-    return nullptr;
-
-  // Look through add of a constant offset on V1, V2, or both operands. This
-  // allows us to interpret the V + C' < C'' range idiom into a proper range.
-  const APInt *Offset1 = nullptr, *Offset2 = nullptr;
-  if (V1 != V2) {
-    Value *X;
-    if (match(V1, m_Add(m_Value(X), m_APInt(Offset1))))
-      V1 = X;
-    if (match(V2, m_Add(m_Value(X), m_APInt(Offset2))))
-      V2 = X;
-  }
-
-  // Look through and with a negative power of 2 mask on V1 or V2. This
-  // detects idioms of the form `(x == A) || ((x & Mask) == A + 1)` where A + 1
-  // is aligned to the mask and A + 1 >= |Mask|. This pattern corresponds to a
-  // contiguous range check, which can be folded into an addition and compare.
-  // The same applies for `(x != A) && ((x & Mask) != A + 1)`.
-  auto AreContiguousRangePredicates = [](CmpPredicate Pred1, CmpPredicate Pred2,
-                                         bool IsAnd) {
-    if (IsAnd)
-      return Pred1 == ICmpInst::ICMP_NE && Pred2 == ICmpInst::ICMP_NE;
-    return Pred1 == ICmpInst::ICMP_EQ && Pred2 == ICmpInst::ICMP_EQ;
-  };
-  const APInt *Mask1 = nullptr, *Mask2 = nullptr;
-  bool MatchedAnd1 = false, MatchedAnd2 = false;
-  if (V1 != V2 && AreContiguousRangePredicates(Pred1, Pred2, IsAnd)) {
+  auto MatchRangeCheck =
+      [](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {
+    const APInt *C;
+    if (!match(ICmp->getOperand(1), m_APInt(C)))
+      return std::nullopt;
+    Value *LHS = ICmp->getOperand(0);
+    CmpPredicate Pred = ICmp->getPredicate();
     Value *X;
-    if (match(V1, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask1)))) &&
-        C1->getBitWidth() == C2->getBitWidth() && *C1 == *C2 + 1 &&
-        C1->uge(Mask1->abs()) && C1->isPowerOf2()) {
-      MatchedAnd1 = true;
-      V1 = X;
-    }
-    if (match(V2, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask2)))) &&
-        C1->getBitWidth() == C2->getBitWidth() && *C2 == *C1 + 1 &&
-        C2->uge(Mask2->abs()) && C2->isPowerOf2()) {
-      MatchedAnd2 = true;
-      V2 = X;
+    // Match (x & NegPow2) ==/!= C
+    const APInt *Mask;
+    if (ICmpInst::isEquality(Pred) &&
+        match(LHS, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask)))) &&
----------------
andjo403 wrote:

do we need the one use check here? there is non for the add below

https://github.com/llvm/llvm-project/pull/158498


More information about the llvm-commits mailing list