[llvm] [InstCombine] Div ceil optimizations (PR #190175)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 10:09:03 PDT 2026


================
@@ -1523,6 +1523,48 @@ static Instruction *foldBoxMultiply(BinaryOperator &I) {
   return nullptr;
 }
 
+/// Return true if X + (Y-1) is provably non-wrapping in X's type
+static bool checkDivCeilNUW(Value *X, Value *Y, BinaryOperator &I,
+                            AssumptionCache &AC, DominatorTree &DT) {
+  ConstantRange CRX = computeConstantRange(X, /*ForSigned=*/false,
+                                           /*UseInstrInfo=*/true, &AC, &I, &DT);
+  ConstantRange CRY = computeConstantRange(Y, /*ForSigned=*/false,
+                                           /*UseInstrInfo=*/true, &AC, &I, &DT);
+  APInt MaxX = CRX.getUnsignedMax();
+  APInt MaxY = CRY.getUnsignedMax();
+  // MaxX + (MaxY - 1) <= UINT_MAX  <==>  MaxX <= UINT_MAX - (MaxY - 1)
+  return !MaxX.ugt(-MaxY);
+}
+
+/// Fold the div_ceil idiom in both forms:
+///   add(udiv(X, Y), zext(icmp ne(urem(X, Y), 0)))
+///     -> udiv(add nuw(X, Y - 1), Y)
+///   add(zext(udiv(X, Y)), zext(icmp ne(urem(X, Y), 0)))
+///     -> zext(udiv(add nuw(X, Y - 1), Y))
+/// The zext form applies when udiv/urem operate in a narrower type than the
+/// add.
+Instruction *InstCombinerImpl::foldDivCeil(BinaryOperator &I) {
+  Value *X, *Y;
+
+  auto UDivPat = m_OneUse(m_UDiv(m_Value(X), m_Value(Y)));
+  auto URemPat = m_OneUse(m_URem(m_Deferred(X), m_Deferred(Y)));
+  auto ICmpPat = m_OneUse(m_SpecificICmp(ICmpInst::ICMP_NE, URemPat, m_Zero()));
+  auto DivPat = m_OneUse(m_ZExtOrSelf(UDivPat));
+  auto ZExtCmpPat = m_OneUse(m_ZExt(ICmpPat));
+
+  if (!match(&I, m_c_Add(DivPat, ZExtCmpPat)) ||
+      !checkDivCeilNUW(X, Y, I, AC, DT))
+    return nullptr;
+
+  Value *YMinusOne = Builder.CreateSub(Y, ConstantInt::get(Y->getType(), 1));
+  Value *NUWAdd = Builder.CreateAdd(X, YMinusOne, "", /*HasNUW=*/true);
----------------
dtcxzyw wrote:

```suggestion
  Value *NUWAdd = Builder.CreateNUWAdd(X, YMinusOne);
```

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


More information about the llvm-commits mailing list