From 3f4d662a6c7d5b9d7779205bda81b1c4ee443449 Mon Sep 17 00:00:00 2001 From: Ivan Butygin Date: Tue, 24 Dec 2024 17:48:45 +0100 Subject: [PATCH] [mlir][IntRangeInference] Fix `arith.ceildivsi` range inference when it includes INT_MIN There is a special case in `arith.ceildivsi` range inference for handling `lhs.smin()==INT_MIN`, but when `lhs` is not a single value, it can cause it to skip entire negative range. Add `lhs.smin() + 1` check to handle it. --- mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp | 10 +++++++++- mlir/test/Dialect/Arith/int-range-interface.mlir | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp index 7a73a94201f1d..1eab4139488bd 100644 --- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp +++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp @@ -386,7 +386,15 @@ mlir::intrange::inferCeilDivS(ArrayRef argRanges) { } return result; }; - return inferDivSRange(lhs, rhs, ceilDivSIFix); + ConstantIntRanges result = inferDivSRange(lhs, rhs, ceilDivSIFix); + if (lhs.smin().isMinSignedValue() && lhs.smax().sgt(lhs.smin())) { + // If lhs range includes INT_MIN and lhs is not a single value, we can + // suddenly wrap to positive val, skipping entire negative range, add + // [INT_MIN + 1, smax()] range to the result to handle this. + auto newLhs = ConstantIntRanges::fromSigned(lhs.smin() + 1, lhs.smax()); + result = result.rangeUnion(inferDivSRange(newLhs, rhs, ceilDivSIFix)); + } + return result; } ConstantIntRanges diff --git a/mlir/test/Dialect/Arith/int-range-interface.mlir b/mlir/test/Dialect/Arith/int-range-interface.mlir index 48a3eb20eb7fb..090af3e79f4a1 100644 --- a/mlir/test/Dialect/Arith/int-range-interface.mlir +++ b/mlir/test/Dialect/Arith/int-range-interface.mlir @@ -249,6 +249,18 @@ func.func @ceil_divsi(%arg0 : index) -> i1 { func.return %10 : i1 } +// There was a bug, which was causing this expr errorneously fold to constant +// CHECK-LABEL: func @ceil_divsi_full_range +// CHECK-SAME: (%[[arg:.*]]: index) +// CHECK: %[[c64:.*]] = arith.constant 64 : index +// CHECK: %[[ret:.*]] = arith.ceildivsi %[[arg]], %[[c64]] : index +// CHECK: return %[[ret]] +func.func @ceil_divsi_full_range(%6: index) -> index { + %c64 = arith.constant 64 : index + %55 = arith.ceildivsi %6, %c64 : index + return %55 : index +} + // CHECK-LABEL: func @ceil_divsi_intmin_bug_115293 // CHECK: %[[ret:.*]] = arith.constant true // CHECK: return %[[ret]]