[llvm] InstCombine: improve optimizations for ceiling division with no overflow (PR #142869)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 4 23:50:21 PDT 2025


================
@@ -1787,6 +1787,50 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
   if (Instruction *Ashr = foldAddToAshr(I))
     return Ashr;
 
+  // Ceiling division by power-of-2:
+  // (X >> log2(N)) + zext(X & (N-1) != 0) --> (X + (N-1)) >> log2(N)
+  // This is valid when adding (N-1) to X doesn't overflow.
+  {
+    Value *X = nullptr, *Cmp = nullptr;
+    const APInt *ShiftAmt = nullptr, *Mask = nullptr;
+    CmpPredicate Pred;
+
+    // Match: (X >> C) + zext((X & Mask) != 0)
+    // or:    zext((X & Mask) != 0) + (X >> C)
+    Value *Op0 = I.getOperand(0);
+    Value *Op1 = I.getOperand(1);
+
+    // Try matching with shift on left, zext on right
+    bool Matched = false;
+    if (match(Op0, m_LShr(m_Value(X), m_APInt(ShiftAmt))) &&
+        match(Op1, m_ZExt(m_Value(Cmp)))) {
+      Matched = match(Cmp, m_ICmp(Pred, m_And(m_Specific(X), m_APInt(Mask)),
+                                  m_ZeroInt()));
+    } else if (match(Op1, m_LShr(m_Value(X), m_APInt(ShiftAmt))) &&
+               match(Op0, m_ZExt(m_Value(Cmp)))) {
+      Matched = match(Cmp, m_ICmp(Pred, m_And(m_Specific(X), m_APInt(Mask)),
+                                  m_ZeroInt()));
+    }
+
+    if (Matched &&
+        Pred == ICmpInst::ICMP_NE &&
+        ShiftAmt && ShiftAmt->uge(1) && ShiftAmt->ult(BitWidth) &&
----------------
dtcxzyw wrote:

You can use `m_LowBitMask(Mask)` in the matching code above, then check `*ShiftAmt == Mask->countr_zero()`.

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


More information about the llvm-commits mailing list