[Mlir-commits] [mlir] [MLIR][Linalg] Fix crash in Generic, Map, Reduce Ops for `getAsmBlockArgumentNames` when region is empty (PR #184743)
Arjun Bhamra
llvmlistbot at llvm.org
Wed Mar 4 21:58:09 PST 2026
https://github.com/abhamra updated https://github.com/llvm/llvm-project/pull/184743
>From 31ec5081db13604144f63b9cd1f249a3ca75bd35 Mon Sep 17 00:00:00 2001
From: Arjun Bhamra <arjun.bhamra25 at gmail.com>
Date: Tue, 3 Mar 2026 14:50:58 -0500
Subject: [PATCH 1/4] notes in inferintrangeinterfaceimpls.cpp,
inferintrangecommon.cpp
---
mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp | 1 +
mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp | 1 +
2 files changed, 2 insertions(+)
diff --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
index 49f89e1bd17f3..e0f43aa420e71 100644
--- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
+++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
@@ -243,6 +243,7 @@ void arith::ExtSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
void arith::TruncIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
+ // NOTE: ISSUE HERE, BE CAREFUL
unsigned destWidth =
ConstantIntRanges::getStorageBitwidth(getResult().getType());
setResultRange(getResult(), truncRange(argRanges[0], destWidth));
diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index 21f07ddce4495..68441ff6c2d13 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -147,6 +147,7 @@ ConstantIntRanges mlir::intrange::truncRange(const ConstantIntRanges &range,
// the range of the resulting value is not contiguous ind includes 0.
// Ex. If you truncate [256, 258] from i16 to i8, you validly get [0, 2],
// but you can't truncate [255, 257] similarly.
+ // NOTE: Issue ends here, in the trunc call when destwidth = 0
bool hasUnsignedRollover =
range.umin().lshr(destWidth) != range.umax().lshr(destWidth);
APInt umin = hasUnsignedRollover ? APInt::getZero(destWidth)
>From 1dcba43d5943e6487dd99d6a30d30685d13fe070 Mon Sep 17 00:00:00 2001
From: Arjun Bhamra <arjun.bhamra25 at gmail.com>
Date: Tue, 3 Mar 2026 14:50:58 -0500
Subject: [PATCH 2/4] notes in inferintrangeinterfaceimpls.cpp,
inferintrangecommon.cpp
---
mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp | 1 +
mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp | 1 +
2 files changed, 2 insertions(+)
diff --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
index 49f89e1bd17f3..e0f43aa420e71 100644
--- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
+++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
@@ -243,6 +243,7 @@ void arith::ExtSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
void arith::TruncIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
+ // NOTE: ISSUE HERE, BE CAREFUL
unsigned destWidth =
ConstantIntRanges::getStorageBitwidth(getResult().getType());
setResultRange(getResult(), truncRange(argRanges[0], destWidth));
diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index 21f07ddce4495..68441ff6c2d13 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -147,6 +147,7 @@ ConstantIntRanges mlir::intrange::truncRange(const ConstantIntRanges &range,
// the range of the resulting value is not contiguous ind includes 0.
// Ex. If you truncate [256, 258] from i16 to i8, you validly get [0, 2],
// but you can't truncate [255, 257] similarly.
+ // NOTE: Issue ends here, in the trunc call when destwidth = 0
bool hasUnsignedRollover =
range.umin().lshr(destWidth) != range.umax().lshr(destWidth);
APInt umin = hasUnsignedRollover ? APInt::getZero(destWidth)
>From d21d4db676621582b100ae306bdf9b4475f7e0d1 Mon Sep 17 00:00:00 2001
From: Arjun Bhamra <arjun.bhamra25 at gmail.com>
Date: Thu, 5 Mar 2026 00:23:46 -0500
Subject: [PATCH 3/4] added guards for empty region in
getAsmBlockArgumentNames, regression test
---
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 6 +++++
.../IR/test-visitors-assume-verified.mlir | 23 +++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 mlir/test/IR/test-visitors-assume-verified.mlir
diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index bfc03cc7436df..9b68a540c52e6 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -1102,6 +1102,8 @@ static void buildGenericRegion(
void GenericOp::getAsmBlockArgumentNames(Region ®ion,
OpAsmSetValueNameFn setNameFn) {
+ if (region.empty())
+ return;
for (Value v : getRegionInputArgs())
setNameFn(v, "in");
for (Value v : getRegionOutputArgs())
@@ -1481,6 +1483,8 @@ static ParseResult parseDstStyleOp(
void MapOp::getAsmBlockArgumentNames(Region ®ion,
OpAsmSetValueNameFn setNameFn) {
+ if (region.empty())
+ return;
for (Value v : getRegionInputArgs())
setNameFn(v, "in");
for (Value v : getRegionOutputArgs())
@@ -1738,6 +1742,8 @@ Speculation::Speculatability MapOp::getSpeculatability() {
void ReduceOp::getAsmBlockArgumentNames(Region ®ion,
OpAsmSetValueNameFn setNameFn) {
+ if (region.empty())
+ return;
for (Value v : getRegionInputArgs())
setNameFn(v, "in");
for (Value v : getRegionOutputArgs())
diff --git a/mlir/test/IR/test-visitors-assume-verified.mlir b/mlir/test/IR/test-visitors-assume-verified.mlir
new file mode 100644
index 0000000000000..8178be1187b16
--- /dev/null
+++ b/mlir/test/IR/test-visitors-assume-verified.mlir
@@ -0,0 +1,23 @@
+// RUN: mlir-opt -test-ir-visitors --mlir-print-assume-verified %s | FileCheck %s
+
+// Regression test: linalg ops implementing getAsmBlockArgumentNames via
+// getRegionInputArgs() used to crash during block erasure in no-skip walks
+// when combined with --mlir-print-assume-verified, because AsmState
+// construction would call getAsmBlockArgumentNames on ops whose regions
+// had already been emptied.
+
+func.func @test_no_skip_block_erasure_linalg_map(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
+ %0 = tensor.empty() : tensor<4xf32>
+ %1 = linalg.map ins(%arg0, %arg1 : tensor<4xf32>, tensor<4xf32>)
+ outs(%0 : tensor<4xf32>)
+ (%in0: f32, %in1: f32, %out: f32) {
+ %2 = arith.addf %in0, %in1 : f32
+ linalg.yield %2 : f32
+ }
+ return %1 : tensor<4xf32>
+}
+
+// CHECK-LABEL: Block post-order erasures (no skip)
+// CHECK: Erasing block ^bb0 from region 0 from operation 'linalg.map'
+// CHECK: Erasing block ^bb0 from region 0 from operation 'func.func'
+// CHECK: Erasing block ^bb0 from region 0 from operation 'builtin.module'
>From 9c42b56c789552193701be4d5274b721c1925c51 Mon Sep 17 00:00:00 2001
From: Arjun Bhamra <arjun.bhamra25 at gmail.com>
Date: Thu, 5 Mar 2026 00:57:18 -0500
Subject: [PATCH 4/4] residual comments removed
---
mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp | 1 -
mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp | 1 -
2 files changed, 2 deletions(-)
diff --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
index e0f43aa420e71..49f89e1bd17f3 100644
--- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
+++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
@@ -243,7 +243,6 @@ void arith::ExtSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
void arith::TruncIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
- // NOTE: ISSUE HERE, BE CAREFUL
unsigned destWidth =
ConstantIntRanges::getStorageBitwidth(getResult().getType());
setResultRange(getResult(), truncRange(argRanges[0], destWidth));
diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index 68441ff6c2d13..21f07ddce4495 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -147,7 +147,6 @@ ConstantIntRanges mlir::intrange::truncRange(const ConstantIntRanges &range,
// the range of the resulting value is not contiguous ind includes 0.
// Ex. If you truncate [256, 258] from i16 to i8, you validly get [0, 2],
// but you can't truncate [255, 257] similarly.
- // NOTE: Issue ends here, in the trunc call when destwidth = 0
bool hasUnsignedRollover =
range.umin().lshr(destWidth) != range.umax().lshr(destWidth);
APInt umin = hasUnsignedRollover ? APInt::getZero(destWidth)
More information about the Mlir-commits
mailing list