[Mlir-commits] [mlir] [mlir][Builtin] Fix crash folding self-referential unrealized_conversion_cast in graph regions (PR #207185)

Anutosh Bhat llvmlistbot at llvm.org
Thu Jul 2 06:25:29 PDT 2026


https://github.com/anutosh491 created https://github.com/llvm/llvm-project/pull/207185

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 r`eplaceAllUsesWith(%0, %0)` (a no-op) followed by eraseOp, which asserted `use_empty()` because the self-use was still live.

Fix 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 at 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 at Anutoshs-MacBook-Air mlir-build % ./bin/mlir-opt -canonicalize bin/a.mlir            
module {
  test.graph_region {
    "test.return"() : () -> ()
  }
}

 anutosh491 at 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%)
```

>From 9c7000d2fcf1d424823b58e97adb45cfbe1fca7a Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Thu, 2 Jul 2026 18:50:24 +0530
Subject: [PATCH] [mlir][Builtin] Fix crash folding self-referential
 unrealized_conversion_cast

---
 mlir/lib/IR/BuiltinDialect.cpp              |  5 +++++
 mlir/test/Dialect/Builtin/canonicalize.mlir | 11 +++++++++++
 2 files changed, 16 insertions(+)

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
+}



More information about the Mlir-commits mailing list