[llvm] [llvm] [InstCombine] fold "icmp eq (X + (V - 1)) & -V, X" to "icmp eq 0, (and X, V - 1)" (PR #152851)

Pavel Skripkin via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 10 06:44:29 PDT 2025


================
@@ -1320,6 +1320,76 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
   return nullptr;
 }
 
+// Fold icmp eq (num + (val - 1)) & -val, num
+//      to
+//      icmp eq 0, (and num, val - 1)
+// For value being power of two
+Instruction *InstCombinerImpl::foldNextMultiply(ICmpInst &Cmp) {
+  Value *Op0 = Cmp.getOperand(0), *Op1 = Cmp.getOperand(1);
+  Value *Neg, *Add, *Num, *Mask, *Value;
+  CmpInst::Predicate Pred = Cmp.getPredicate();
+  const APInt *NegConst, *MaskConst, *NumCost;
+
+  if (!ICmpInst::isEquality(Pred))
+    return nullptr;
+
+  // Match num + neg
+  if (!match(Op0, m_c_And(m_Value(Add), m_Value(Neg))))
+    return nullptr;
+
+  // Match num & mask and handle commutative care
+  if (!match(Add, m_c_Add(m_Value(Num), m_Value(Mask)))) {
+    if (match(Neg, m_c_Add(m_Value(Num), m_Value(Mask)))) {
+      std::swap(Add, Neg);
+    } else {
+      return nullptr;
+    }
+  }
+
+  // Check the constant case
+  if (match(Neg, m_APInt(NegConst)) && match(Mask, m_APInt(MaskConst))) {
+    // Mask + 1 should be a power-of-two
+    if (!(*MaskConst + 1).isPowerOf2())
+      return nullptr;
+
+    // Neg = -(Mask + 1)
+    if (*NegConst != -(*MaskConst + 1))
+      return nullptr;
+  } else {
+    // Match neg = sub 0, val
+    if (!match(Neg, m_Sub(m_Zero(), m_Value(Value))))
+      return nullptr;
+
+    // mask = add %val, -1. No commutative here, since it's canonical
+    // representation for sub %val, -1
+    if (!match(Mask, m_Add(m_Value(Value), m_AllOnes()))) {
+      if (match(Num, m_Add(m_Value(Value), m_AllOnes()))) {
+        std::swap(Mask, Num);
+      } else {
+        return nullptr;
+      }
+    }
+
+    // Value should be a known power-of-two.
+    if (!isKnownToBeAPowerOfTwo(Value, false, &Cmp))
+      return nullptr;
+  }
+
+  // Guard against weird special-case where Op1 gets optimized to constant.
+  // Leave it constant fonder.
+  if (match(Op1, m_APInt(NumCost)))
+    return nullptr;
+
+  if (!match(Op1, m_Value(Num)))
+    return nullptr;
----------------
pskrgag wrote:

Yeah, that exactly what I wanted, but didn't know about `m_Specific`. Thanks!

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


More information about the llvm-commits mailing list