[Mlir-commits] [mlir] [MLIR][IntRange] Materialize known constant values only when the value type is integer-like (PR #196133)
Jeremy Kun
llvmlistbot at llvm.org
Wed May 6 14:54:53 PDT 2026
https://github.com/j2kun updated https://github.com/llvm/llvm-project/pull/196133
>From 2005ad12f7d7cdc491e9adae8365c0fd319c9952 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 6 May 2026 10:27:25 -0700
Subject: [PATCH 1/3] add reproducing crash
---
.../Dialect/Arith/int-range-opts-crash.mlir | 13 ++++++++++
mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 24 +++++++++++++++++++
mlir/test/lib/Dialect/Test/TestOps.td | 11 +++++++++
3 files changed, 48 insertions(+)
create mode 100644 mlir/test/Dialect/Arith/int-range-opts-crash.mlir
diff --git a/mlir/test/Dialect/Arith/int-range-opts-crash.mlir b/mlir/test/Dialect/Arith/int-range-opts-crash.mlir
new file mode 100644
index 0000000000000..fa763c163160d
--- /dev/null
+++ b/mlir/test/Dialect/Arith/int-range-opts-crash.mlir
@@ -0,0 +1,13 @@
+// RUN: mlir-opt -int-range-optimizations %s | FileCheck %s
+
+// CHECK-LABEL: func.func @repro_crash() -> !test.i32 {
+func.func @repro_crash() -> !test.i32 {
+ %cst = arith.constant 1 : i32
+ // CHECK: %[[RES:.*]] = test.region_type_changer
+ %0 = "test.region_type_changer"(%cst) ({
+ ^bb0(%arg0: i32):
+ "test.types_compat_yield"(%arg0) : (i32) -> ()
+ }) : (i32) -> !test.i32
+ // CHECK: return %[[RES]] : !test.i32
+ return %0 : !test.i32
+}
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index 340b44b14dd96..73eed41acc3e8 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -1546,6 +1546,30 @@ bool TestLoopTypesCompatOp::areTypesCompatible(Type lhs, Type rhs) {
return lhs == rhs || (isa<IntegerType>(lhs) && isa<IntegerType>(rhs));
}
+void TestRegionTypeChangerOp::getSuccessorRegions(
+ RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
+ if (point.isParent())
+ regions.emplace_back(&getBody());
+ else
+ regions.push_back(RegionSuccessor::parent());
+}
+
+OperandRange
+TestRegionTypeChangerOp::getEntrySuccessorOperands(RegionSuccessor) {
+ return getEntries();
+}
+
+ValueRange
+TestRegionTypeChangerOp::getSuccessorInputs(RegionSuccessor successor) {
+ if (successor.isParent())
+ return getResults();
+ return getBody().getArguments();
+}
+
+bool TestRegionTypeChangerOp::areTypesCompatible(Type lhs, Type rhs) {
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// TestVersionedOpA
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 348ff5d7f4ea0..90cda01f2704b 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -2799,6 +2799,17 @@ def TestLoopTypesCompatOp : TEST_Op<"loop_types_compat",
let regions = (region SizedRegion<1>:$body);
}
+def TestRegionTypeChangerOp : TEST_Op<"region_type_changer",
+ [DeclareOpInterfaceMethods<RegionBranchOpInterface,
+ ["getEntrySuccessorOperands", "getSuccessorInputs",
+ "areTypesCompatible"]>,
+ RecursiveMemoryEffects]> {
+ let arguments = (ins Variadic<AnyType>:$entries);
+ let results = (outs Variadic<AnyType>:$results);
+ let regions = (region SizedRegion<1>:$body);
+ let assemblyFormat = "`(` $entries `)` $body `:` functional-type($entries, $results) attr-dict";
+}
+
//===----------------------------------------------------------------------===//
// Test TableGen generated build() methods
//===----------------------------------------------------------------------===//
>From 890a8b73960f2d317f863ea7e8d7d63b49e4d226 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 6 May 2026 10:39:00 -0700
Subject: [PATCH 2/3] Add a guard for attempts to materialize non-integer types
---
.../Arith/Transforms/IntRangeOptimizations.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp b/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
index 85578c22799c6..559073951c3e3 100644
--- a/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
@@ -71,6 +71,10 @@ LogicalResult maybeReplaceWithConstant(DataFlowSolver &solver,
return failure();
Type type = value.getType();
+ // If the type or element type is non-integral, the attribute constructor
+ // will crash, so eagerly check for an integer type to avoid this.
+ if (!getElementTypeOrSelf(type).isIntOrIndex())
+ return failure();
Location loc = value.getLoc();
Operation *maybeDefiningOp = value.getDefiningOp();
Dialect *valueDialect =
@@ -133,8 +137,14 @@ struct MaterializeKnownConstantValues : public RewritePattern {
if (matchPattern(op, m_Constant()))
return failure();
+ // We need to check isIntOrIndex() here as well to avoid infinite loops in the
+ // greedy pattern rewriter. If we only check it in maybeReplaceWithConstant,
+ // this lambda might still return true for non-integral types, causing the
+ // pattern to match and claim success without making any changes, leading to
+ // non-convergence.
auto needsReplacing = [&](Value v) {
- return getMaybeConstantValue(solver, v).has_value() && !v.use_empty();
+ return getElementTypeOrSelf(v.getType()).isIntOrIndex() &&
+ getMaybeConstantValue(solver, v).has_value() && !v.use_empty();
};
bool hasConstantResults = llvm::any_of(op->getResults(), needsReplacing);
if (op->getNumRegions() == 0)
>From c6e44b3c983be0b2ba14717fdaab78f8e64b71da Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 6 May 2026 14:54:31 -0700
Subject: [PATCH 3/3] format
---
.../Dialect/Arith/Transforms/IntRangeOptimizations.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp b/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
index 559073951c3e3..9fcda39089b2c 100644
--- a/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/IntRangeOptimizations.cpp
@@ -137,11 +137,11 @@ struct MaterializeKnownConstantValues : public RewritePattern {
if (matchPattern(op, m_Constant()))
return failure();
- // We need to check isIntOrIndex() here as well to avoid infinite loops in the
- // greedy pattern rewriter. If we only check it in maybeReplaceWithConstant,
- // this lambda might still return true for non-integral types, causing the
- // pattern to match and claim success without making any changes, leading to
- // non-convergence.
+ // We need to check isIntOrIndex() here as well to avoid infinite loops in
+ // the greedy pattern rewriter. If we only check it in
+ // maybeReplaceWithConstant, this lambda might still return true for
+ // non-integral types, causing the pattern to match and claim success
+ // without making any changes, leading to non-convergence.
auto needsReplacing = [&](Value v) {
return getElementTypeOrSelf(v.getType()).isIntOrIndex() &&
getMaybeConstantValue(solver, v).has_value() && !v.use_empty();
More information about the Mlir-commits
mailing list