[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