[Mlir-commits] [mlir] [mlir][IntRangeAnalysis] Fix assertion in inferAffineExpr for mod with range crossing modulus boundary (PR #188842)
Zhewen Yu
llvmlistbot at llvm.org
Thu Mar 26 14:02:08 PDT 2026
https://github.com/Yu-Zhewen created https://github.com/llvm/llvm-project/pull/188842
The "small range with constant divisor" optimization in inferAffineExpr for AffineExprKind::Mod assumed that if the dividend range span (lhsMax - lhsMin) is less than the divisor, then the mod results form a contiguous range. This is not always true, as the range can straddle a modulus boundary.
For example, [14, 17] mod 8:
- Span is 3 < 8, so the old condition passed
- But 14%8=6 and 17%8=1 (wraps at 16)
- umin=6, umax=1 → assertion umin.ule(umax) fails
The fix adds a same-quotient check (lhsMin/rhs == lhsMax/rhs) to ensure both endpoints fall within the same modular period. When they don't, we fall back to the conservative [0, divisor-1] range.
Assisted-by: Cursor (Claude)
>From 1a914a86be232614fa8bb43b68d7aa1a1028b386 Mon Sep 17 00:00:00 2001
From: Yu-Zhewen <zhewenyu at amd.com>
Date: Thu, 26 Mar 2026 20:57:24 +0000
Subject: [PATCH] fix bound
Signed-off-by: Yu-Zhewen <zhewenyu at amd.com>
---
mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp | 15 +++++++--------
mlir/test/Dialect/Affine/int-range-interface.mlir | 12 ++++++++++++
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index 21f07ddce4495..067000116a46e 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -854,17 +854,16 @@ mlir::intrange::inferAffineExpr(AffineExpr expr,
umax = lhsMax;
}
// Special case: sweeping out a contiguous range with constant divisor.
- // Only applies when dividend is non-negative to ensure result range is
- // contiguous.
+ // Only applies when dividend is non-negative and the range does not
+ // cross a modulus boundary (same quotient), ensuring contiguity.
else if (rhsMin == rhsMax && lhsMin.isNonNegative() &&
- (lhsMax - lhsMin).ult(rhsMax)) {
- // For non-negative dividends, Euclidean mod is same as unsigned
- // remainder.
+ (lhsMax - lhsMin).ult(rhsMax) &&
+ lhsMin.udiv(rhsMax) == lhsMax.udiv(rhsMax)) {
+ // For non-negative dividends within the same modular period,
+ // Euclidean mod is same as unsigned remainder and the result is
+ // contiguous.
umin = lhsMin.urem(rhsMax);
umax = lhsMax.urem(rhsMax);
- // Result should be contiguous since we're not wrapping around.
- assert(umin.ule(umax) &&
- "Range should be contiguous for non-negative dividend");
}
return ConstantIntRanges::fromUnsigned(umin, umax);
diff --git a/mlir/test/Dialect/Affine/int-range-interface.mlir b/mlir/test/Dialect/Affine/int-range-interface.mlir
index ca8df8a9e5788..ac64ad09ee244 100644
--- a/mlir/test/Dialect/Affine/int-range-interface.mlir
+++ b/mlir/test/Dialect/Affine/int-range-interface.mlir
@@ -147,6 +147,18 @@ func.func @affine_apply_mod_variable_divisor() -> index {
func.return %1 : index
}
+// CHECK-LABEL: func @affine_apply_mod_cross_boundary
+// CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index}
+func.func @affine_apply_mod_cross_boundary() -> index {
+ %d0 = test.with_bounds { umin = 14 : index, umax = 17 : index,
+ smin = 14 : index, smax = 17 : index } : index
+ // Range [14, 17] spans a mod-8 boundary (at 16): 14%8=6, 17%8=1.
+ // Span 3 < 8 but the range wraps, so we fall back to [0, 7].
+ %0 = affine.apply affine_map<(d0) -> (d0 mod 8)>(%d0)
+ %1 = test.reflect_bounds %0 : index
+ func.return %1 : index
+}
+
// CHECK-LABEL: func @affine_apply_mod_negative_dividend
// CHECK: test.reflect_bounds {smax = 3 : index, smin = 0 : index, umax = 3 : index, umin = 0 : index}
func.func @affine_apply_mod_negative_dividend() -> index {
More information about the Mlir-commits
mailing list