[Mlir-commits] [mlir] [mlir] Guard affine div ranges (PR #206264)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Jun 27 09:28:15 PDT 2026
https://github.com/mygitljf created https://github.com/llvm/llvm-project/pull/206264
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
>From 36aa50509987236eb666f0b9fb977f004508ba6a Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Sun, 28 Jun 2026 00:18:49 +0000
Subject: [PATCH] [mlir] Guard affine div ranges
---
.../Interfaces/Utils/InferIntRangeCommon.cpp | 13 +++++++++-
.../Dialect/Affine/int-range-interface.mlir | 24 +++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
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 {
More information about the Mlir-commits
mailing list