[Mlir-commits] [mlir] [mlir][test] Fix crash in TestWithBoundsOp with mismatched attribute width (PR #184093)

Mehdi Amini llvmlistbot at llvm.org
Mon Mar 2 02:42:32 PST 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/184093

`TestWithBoundsOp::inferResultRanges` was passing the stored APInt bound values directly to `setResultRanges` without checking whether their bit width matched the result type. When bounds were stored using a wider type (e.g., `10 : i64` for an `i8` result), the `ConstantIntRanges` invariant was violated: the APInts had width 64 while the integer type had width 8.

Downstream consumers such as `TestReflectBoundsOp::inferResultRanges` would then call `Builder::getIntegerAttr(i8Type, 64-bit-APInt)`, which asserts that the bit widths match, causing a crash.

Fix by truncating or extending the stored APInts to match the result type's storage width in `TestWithBoundsOp::inferResultRanges`.

Fixes #120882

>From 82e6bcdbf42ecd263f449a62144f9cf2fa5581d2 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sun, 1 Mar 2026 16:54:47 -0800
Subject: [PATCH] [mlir][test] Fix crash in TestWithBoundsOp with mismatched
 attribute width

`TestWithBoundsOp::inferResultRanges` was passing the stored APInt bound
values directly to `setResultRanges` without checking whether their bit
width matched the result type. When bounds were stored using a wider type
(e.g., `10 : i64` for an `i8` result), the `ConstantIntRanges` invariant
was violated: the APInts had width 64 while the integer type had width 8.

Downstream consumers such as `TestReflectBoundsOp::inferResultRanges`
would then call `Builder::getIntegerAttr(i8Type, 64-bit-APInt)`, which
asserts that the bit widths match, causing a crash.

Fix by truncating or extending the stored APInts to match the result
type's storage width in `TestWithBoundsOp::inferResultRanges`.

Fixes #120882
---
 .../infer-int-range-test-ops.mlir             | 12 +++++++++
 mlir/test/lib/Dialect/Test/TestOpDefs.cpp     | 25 ++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir b/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir
index c6344447d9f74..90386052f7107 100644
--- a/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir
+++ b/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir
@@ -200,3 +200,15 @@ func.func @multiple_loop_ivs(%arg0: memref<?x64xi32>) {
   }
   return
 }
+
+// Verify that test.with_bounds with mismatched attribute width (e.g., i64
+// bounds for an i8 result) does not crash but instead truncates the bounds
+// to the result type's width. See: https://github.com/llvm/llvm-project/issues/120882
+// CHECK-LABEL: func @with_bounds_mismatched_width
+// CHECK: test.reflect_bounds {smax = 15 : si8, smin = 10 : si8, umax = 15 : ui8, umin = 10 : ui8}
+func.func @with_bounds_mismatched_width() -> i8 {
+  %0 = test.with_bounds { umin = 10 : i64, umax = 15 : i64,
+                           smin = 10 : i64, smax = 15 : i64 } : i8
+  %1 = test.reflect_bounds %0 : i8
+  return %1 : i8
+}
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index d2826cc42b270..7cf608b66c657 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -878,7 +878,30 @@ LogicalResult TestVerifiersOp::verifyRegions() {
 
 void TestWithBoundsOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                          SetIntRangeFn setResultRanges) {
-  setResultRanges(getResult(), {getUmin(), getUmax(), getSmin(), getSmax()});
+  APInt umin = getUmin(), umax = getUmax(), smin = getSmin(), smax = getSmax();
+  // Ensure the APInt widths match the result type's expected storage width.
+  // The stored attributes may use a different width (e.g., i64 bounds for an
+  // i8 result), which would violate the ConstantIntRanges invariant.
+  Type type = getElementTypeOrSelf(getResult().getType());
+  unsigned targetWidth = 0;
+  if (type.isIndex())
+    targetWidth = IndexType::kInternalStorageBitWidth;
+  else if (auto intTy = llvm::dyn_cast<IntegerType>(type))
+    targetWidth = intTy.getWidth();
+  if (targetWidth != 0 && umin.getBitWidth() != targetWidth) {
+    if (umin.getBitWidth() > targetWidth) {
+      umin = umin.trunc(targetWidth);
+      umax = umax.trunc(targetWidth);
+      smin = smin.trunc(targetWidth);
+      smax = smax.trunc(targetWidth);
+    } else {
+      umin = umin.zext(targetWidth);
+      umax = umax.zext(targetWidth);
+      smin = smin.sext(targetWidth);
+      smax = smax.sext(targetWidth);
+    }
+  }
+  setResultRanges(getResult(), {umin, umax, smin, smax});
 }
 
 //===----------------------------------------------------------------------===//



More information about the Mlir-commits mailing list