[Mlir-commits] [mlir] [mlir] Guard affine div ranges (PR #206264)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Jun 27 09:28:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: lianjinfeng2003 (mygitljf)
<details>
<summary>Changes</summary>
I narrowed this down to affine ceil/floor division range inference creating an impossible positive divisor range when the divisor range was known to be zero. This patch makes the positive clamp fall back conservatively instead of returning reversed bounds, and adds a defensive signed-division guard so invalid divisor ranges cannot reach endpoint division by zero.
I added affine int-range regressions for the zero-divisor range path.
Fixes #<!-- -->206095
---
Full diff: https://github.com/llvm/llvm-project/pull/206264.diff
2 Files Affected:
- (modified) mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp (+12-1)
- (modified) mlir/test/Dialect/Affine/int-range-interface.mlir (+24)
``````````diff
diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index c9f49fda726e7..f78a45a1dc085 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -342,11 +342,19 @@ static ConstantIntRanges inferDivSRange(const ConstantIntRanges &lhs,
DivisionFixupFn fixup) {
const APInt &lhsMin = lhs.smin(), &lhsMax = lhs.smax(), &rhsMin = rhs.smin(),
&rhsMax = rhs.smax();
- bool canDivide = rhsMin.isStrictlyPositive() || rhsMax.isNegative();
+ // Only enumerate endpoints when the signed divisor range is ordered and
+ // wholly non-zero; otherwise fall back to the conservative result below.
+ bool isOrdered = rhsMin.sle(rhsMax);
+ bool canDivide =
+ isOrdered &&
+ ((rhsMin.isStrictlyPositive() && rhsMax.isStrictlyPositive()) ||
+ (rhsMin.isNegative() && rhsMax.isNegative()));
if (canDivide) {
auto sdiv = [&fixup](const APInt &a,
const APInt &b) -> std::optional<APInt> {
+ if (b.isZero())
+ return std::nullopt;
bool overflowed = false;
APInt result = a.sdiv_ov(b, overflowed);
return overflowed ? std::optional<APInt>() : fixup(a, b, result);
@@ -779,6 +787,9 @@ static ConstantIntRanges clampToPositive(const ConstantIntRanges &val) {
APInt one(width, 1);
APInt clampedUMin = val.umin().ult(one) ? one : val.umin();
APInt clampedSMin = val.smin().slt(one) ? one : val.smin();
+ // The positive slice may be empty, which ConstantIntRanges cannot represent.
+ if (clampedUMin.ugt(val.umax()) || clampedSMin.sgt(val.smax()))
+ return ConstantIntRanges::maxRange(width);
return ConstantIntRanges::fromUnsigned(clampedUMin, val.umax())
.intersection(ConstantIntRanges::fromSigned(clampedSMin, val.smax()));
}
diff --git a/mlir/test/Dialect/Affine/int-range-interface.mlir b/mlir/test/Dialect/Affine/int-range-interface.mlir
index ac64ad09ee244..f7b3cde771713 100644
--- a/mlir/test/Dialect/Affine/int-range-interface.mlir
+++ b/mlir/test/Dialect/Affine/int-range-interface.mlir
@@ -52,6 +52,30 @@ func.func @affine_apply_ceildiv() -> index {
func.return %1 : index
}
+// CHECK-LABEL: func @affine_apply_floordiv_zero_symbol
+// CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -1 : index, umin = 0 : index}
+func.func @affine_apply_floordiv_zero_symbol() -> index {
+ %d0 = test.with_bounds { umin = 5 : index, umax = 10 : index,
+ smin = 5 : index, smax = 10 : index } : index
+ %s0 = test.with_bounds { umin = 0 : index, umax = 0 : index,
+ smin = 0 : index, smax = 0 : index } : index
+ %0 = affine.apply affine_map<(d0)[s0] -> (d0 floordiv s0)>(%d0)[%s0]
+ %1 = test.reflect_bounds %0 : index
+ func.return %1 : index
+}
+
+// CHECK-LABEL: func @affine_apply_ceildiv_zero_symbol
+// CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -1 : index, umin = 0 : index}
+func.func @affine_apply_ceildiv_zero_symbol() -> index {
+ %d0 = test.with_bounds { umin = 5 : index, umax = 10 : index,
+ smin = 5 : index, smax = 10 : index } : index
+ %s0 = test.with_bounds { umin = 0 : index, umax = 0 : index,
+ smin = 0 : index, smax = 0 : index } : index
+ %0 = affine.apply affine_map<(d0)[s0] -> (d0 ceildiv s0)>(%d0)[%s0]
+ %1 = test.reflect_bounds %0 : index
+ func.return %1 : index
+}
+
// CHECK-LABEL: func @affine_apply_mod
// CHECK: test.reflect_bounds {smax = 3 : index, smin = 0 : index, umax = 3 : index, umin = 0 : index}
func.func @affine_apply_mod() -> index {
``````````
</details>
https://github.com/llvm/llvm-project/pull/206264
More information about the Mlir-commits
mailing list