[Mlir-commits] [mlir] [mlir] Compute ceildivs consistently for INT_MIN operands (PR #215696)

Jakub Kuderski llvmlistbot at llvm.org
Wed Aug 12 06:35:37 PDT 2026


================
@@ -245,27 +245,29 @@ OpFoldResult DivUOp::fold(FoldAdaptor adaptor) {
 // CeilDivSOp
 //===----------------------------------------------------------------------===//
 
-/// Compute `ceildivs(n, m)` as `x = m > 0 ? -1 : 1` and then
-/// `n*m > 0 ? (n+x)/m + 1 : -(-n/m)`.
+/// Compute `ceildivs(n, m)` as `z = n / m` and then
+/// `z*m != n && (n < 0) == (m < 0) ? z + 1 : z`.
 static std::optional<APInt> calculateCeilDivS(const APInt &n, const APInt &m) {
   // Don't fold division by zero.
   if (m.isZero())
     return std::nullopt;
-  // Short-circuit the zero case.
-  if (n.isZero())
-    return n;
 
-  bool mGtZ = m.sgt(0);
-  if (n.sgt(0) != mGtZ) {
-    // If the operands have different signs, compute the negative result. Signed
-    // division overflow is not possible, since if `m == -1`, `n` can be at most
-    // `INT_MAX`, and `-INT_MAX != INT_MIN` in two's complement.
-    return -(-n).sdiv(m);
-  }
-  // Otherwise, compute the positive result. Signed division overflow is not
-  // possible since if `m == -1`, `x` will be `1`.
-  int64_t x = mGtZ ? -1 : 1;
-  return (n + x).sdiv(m) + 1;
+  // sdiv truncates towards zero, so it already rounds up whenever the exact
+  // quotient is negative. Neither operand is negated, so `INT_MIN` folds like
+  // any other dividend.
+  bool overflowed = false;
+  APInt quotient = n.sdiv_ov(m, overflowed);
----------------
kuhar wrote:

Can we simplify the representable case by returning `APIntOps::RoundingSDiv(n, m, APInt::Rounding::UP)` after the existing `sdiv_ov` guard? That helper implements the same remainder/sign correction, so this avoids maintaining another copy while preserving the required `INT_MIN / -1` rejection.

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


More information about the Mlir-commits mailing list