[Mlir-commits] [mlir] [mlir][Builtin] Fix crash folding self-referential unrealized_conversion_cast in graph regions (PR #207185)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jul 2 06:33:18 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core
Author: Anutosh Bhat (anutosh491)
<details>
<summary>Changes</summary>
Fix #<!-- -->205064
Graph regions permit use-def cycles. When an `unrealized_conversion_cast`uses its own result as an operand and the input/output types match, the fold returned success with the operand (= the result itself) as the replacement value. `replaceOp` then called `replaceAllUsesWith(%0, %0)` (a no-op) followed by `eraseOp`, which asserted `use_empty()` because the self-use was still live.
This can be fixed by bailing out of the fold when any operand is produced by this op itself. The greedy rewriter then correctly DCEs the op by dropping the self-use before erasing. As a result we have the following
```
anutosh491@<!-- -->Anutoshs-MacBook-Air mlir-build % cat bin/a.mlir
module {
test.graph_region {
%0 = builtin.unrealized_conversion_cast %0 : i32 to i32
"test.return"() : () -> ()
}
}%
anutosh491@<!-- -->Anutoshs-MacBook-Air mlir-build % ./bin/mlir-opt -canonicalize bin/a.mlir
module {
test.graph_region {
"test.return"() : () -> ()
}
}
anutosh491@<!-- -->Anutoshs-MacBook-Air mlir-build % ./bin/llvm-lit ../mlir/test/Dialect/Builtin/canonicalize.mlir -v
-- Testing: 1 tests, 1 workers --
PASS: MLIR :: Dialect/Builtin/canonicalize.mlir (1 of 1)
Testing Time: 0.12s
Total Discovered Tests: 1
Passed: 1 (100.00%)
```
---
Full diff: https://github.com/llvm/llvm-project/pull/207185.diff
2 Files Affected:
- (modified) mlir/lib/IR/BuiltinDialect.cpp (+5)
- (modified) mlir/test/Dialect/Builtin/canonicalize.mlir (+11)
``````````diff
diff --git a/mlir/lib/IR/BuiltinDialect.cpp b/mlir/lib/IR/BuiltinDialect.cpp
index c88b328282275..00cad06122dd8 100644
--- a/mlir/lib/IR/BuiltinDialect.cpp
+++ b/mlir/lib/IR/BuiltinDialect.cpp
@@ -201,6 +201,11 @@ UnrealizedConversionCastOp::fold(FoldAdaptor adaptor,
ResultRange results = getOutputs();
if (operands.getType() == results.getType()) {
+ // Skip if any operand is this op's own result (self-referential cycle).
+ if (llvm::any_of(operands, [this](Value v) {
+ return v.getDefiningOp() == getOperation();
+ }))
+ return failure();
foldResults.append(operands.begin(), operands.end());
return success();
}
diff --git a/mlir/test/Dialect/Builtin/canonicalize.mlir b/mlir/test/Dialect/Builtin/canonicalize.mlir
index 2e36b7ee371c3..537868e990d78 100644
--- a/mlir/test/Dialect/Builtin/canonicalize.mlir
+++ b/mlir/test/Dialect/Builtin/canonicalize.mlir
@@ -23,3 +23,14 @@ func.func @multiple_conversion_casts_failure(%arg0: i32, %arg1: i32, %arg2: i64)
%outputs:2 = builtin.unrealized_conversion_cast %arg2, %inputs#1 : i64, i64 to i32, i32
return %outputs#0, %outputs#1 : i32, i32
}
+
+// Test a self-referential cast in a graph region must not crash.
+// CHECK-LABEL: func @self_referential_cast
+// CHECK-NOT: unrealized_conversion_cast
+func.func @self_referential_cast() {
+ test.graph_region {
+ %0 = builtin.unrealized_conversion_cast %0 : i32 to i32
+ "test.return"() : () -> ()
+ }
+ return
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/207185
More information about the Mlir-commits
mailing list