[Mlir-commits] [mlir] [arith][mlir] Fixed a bug in CeilDiv with neg values (PR #90855)

Balaji V. Iyer. llvmlistbot at llvm.org
Thu May 2 14:10:20 PDT 2024


================
@@ -652,16 +652,15 @@ OpFoldResult arith::CeilDivSIOp::fold(FoldAdaptor adaptor) {
           APInt posB = zero.ssub_ov(b, overflowOrDiv0);
           return signedCeilNonnegInputs(posA, posB, overflowOrDiv0);
         }
-        if (!aGtZero && bGtZero) {
-          // A is negative, b is positive, return - ( -a / b).
-          APInt posA = zero.ssub_ov(a, overflowOrDiv0);
-          APInt div = posA.sdiv_ov(b, overflowOrDiv0);
-          return zero.ssub_ov(div, overflowOrDiv0);
-        }
-        // A is positive, b is negative, return - (a / -b).
-        APInt posB = zero.ssub_ov(b, overflowOrDiv0);
-        APInt div = a.sdiv_ov(posB, overflowOrDiv0);
-        return zero.ssub_ov(div, overflowOrDiv0);
+        // If either divisor or dividend is negative, then take their absolute
+        // value and then do a normal signedCeil Division, but add 1 to bring
+        // the quotient down. In essense, Ceil Division with one of the values
+        // negative works like a floorDivision with negated quotient.
----------------
bviyer wrote:

As per this https://mlir.llvm.org/doxygen/ArithOps_8cpp_source.html#l00638 the formula for `signedCeilNonnegInputs` is `(a-1)/b + 1` So, we are subtracting 1 from it (as seen in code) and then negating the whole thing.

`-1 * [(a-1)/b + 1 - 1]`

Which is same as:

`-1 * [(a-1)/b + 1] + 1`. 

The 2nd formula is what I mentioned in the comment.

I had what I did in the comment, but later one found that subracting one before negating the whole thing is better. I will fix the comment soon.

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


More information about the Mlir-commits mailing list