[Mlir-commits] [mlir] [mlir][test-ir-visitors] Fix noSkipBlockErasure for blocks providing global context (PR #181320)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Feb 16 12:43:11 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Prathamesh Tagore (meshtag)

<details>
<summary>Changes</summary>

The pass checks if something is pointing to the current block in
testNoSkipErasureCallbacks() inside noSkipBlockErasure() callback and erases
it if no one is pointing to it. However, it doesn't consider the fact that
the current block might be providing global context to other blocks in the
same parent op even if no one is pointing to it (see the attached test for an
example of this). Erasing this block would then lead to invalid IR. We solve
this by dropping uses from operations within the same parent block holding
operation. This way, we can safely erase the block if nothing outside the
surrounding region still needs it.

Fixes https://github.com/llvm/llvm-project/issues/178099

---

Patch is 20.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181320.diff


2 Files Affected:

- (modified) mlir/test/IR/visitors.mlir (+135-118) 
- (modified) mlir/test/lib/IR/TestVisitors.cpp (+18) 


``````````diff
diff --git a/mlir/test/IR/visitors.mlir b/mlir/test/IR/visitors.mlir
index ec7712a45d388..e8efe327d9810 100644
--- a/mlir/test/IR/visitors.mlir
+++ b/mlir/test/IR/visitors.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt -test-ir-visitors -allow-unregistered-dialect -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -test-ir-visitors -split-input-file %s | FileCheck %s
 
 // Verify the different configurations of IR visitors.
 // Constant, yield and other terminator ops are not matched for simplicity.
@@ -10,13 +10,13 @@ func.func @structured_cfg() {
   %c1 = arith.constant 1 : index
   %c10 = arith.constant 10 : index
   scf.for %i = %c1 to %c10 step %c1 {
-    %cond = "use0"(%i) : (index) -> (i1)
+    %cond = "test.zero"(%i) : (index) -> (i1)
     scf.if %cond {
-      "use1"(%i) : (index) -> ()
+      "test.one"(%i) : (index) -> ()
     } else {
-      "use2"(%i) : (index) -> ()
+      "test.two"(%i) : (index) -> ()
     }
-    "use3"(%i) : (index) -> ()
+    "test.three"(%i) : (index) -> ()
   } {walk_blocks, walk_regions}
   return
 }
@@ -25,11 +25,11 @@ func.func @structured_cfg() {
 // CHECK:       Visiting op 'builtin.module'
 // CHECK:       Visiting op 'func.func'
 // CHECK:       Visiting op 'scf.for'
-// CHECK:       Visiting op 'use0'
+// CHECK:       Visiting op 'test.zero'
 // CHECK:       Visiting op 'scf.if'
-// CHECK:       Visiting op 'use1'
-// CHECK:       Visiting op 'use2'
-// CHECK:       Visiting op 'use3'
+// CHECK:       Visiting op 'test.one'
+// CHECK:       Visiting op 'test.two'
+// CHECK:       Visiting op 'test.three'
 // CHECK:       Visiting op 'func.return'
 
 // CHECK-LABEL: Block pre-order visits
@@ -47,11 +47,11 @@ func.func @structured_cfg() {
 // CHECK:       Visiting region 1 from operation 'scf.if'
 
 // CHECK-LABEL: Op post-order visits
-// CHECK:       Visiting op 'use0'
-// CHECK:       Visiting op 'use1'
-// CHECK:       Visiting op 'use2'
+// CHECK:       Visiting op 'test.zero'
+// CHECK:       Visiting op 'test.one'
+// CHECK:       Visiting op 'test.two'
 // CHECK:       Visiting op 'scf.if'
-// CHECK:       Visiting op 'use3'
+// CHECK:       Visiting op 'test.three'
 // CHECK:       Visiting op 'scf.for'
 // CHECK:       Visiting op 'func.return'
 // CHECK:       Visiting op 'func.func'
@@ -74,13 +74,13 @@ func.func @structured_cfg() {
 // CHECK-LABEL: Op reverse post-order visits
 // CHECK:       Visiting op 'func.return'
 // CHECK:       Visiting op 'scf.yield'
-// CHECK:       Visiting op 'use3'
+// CHECK:       Visiting op 'test.three'
 // CHECK:       Visiting op 'scf.yield'
-// CHECK:       Visiting op 'use2'
+// CHECK:       Visiting op 'test.two'
 // CHECK:       Visiting op 'scf.yield'
-// CHECK:       Visiting op 'use1'
+// CHECK:       Visiting op 'test.one'
 // CHECK:       Visiting op 'scf.if'
-// CHECK:       Visiting op 'use0'
+// CHECK:       Visiting op 'test.zero'
 // CHECK:       Visiting op 'scf.for'
 // CHECK:       Visiting op 'arith.constant'
 // CHECK:       Visiting op 'arith.constant'
@@ -116,11 +116,11 @@ func.func @structured_cfg() {
 // CHECK:       Erasing block ^bb0 from region 0 from operation 'scf.for'
 
 // CHECK-LABEL: Op post-order erasures (skip)
-// CHECK:       Erasing op 'use0'
-// CHECK:       Erasing op 'use1'
-// CHECK:       Erasing op 'use2'
+// CHECK:       Erasing op 'test.zero'
+// CHECK:       Erasing op 'test.one'
+// CHECK:       Erasing op 'test.two'
 // CHECK:       Erasing op 'scf.if'
-// CHECK:       Erasing op 'use3'
+// CHECK:       Erasing op 'test.three'
 // CHECK:       Erasing op 'scf.for'
 // CHECK:       Erasing op 'func.return'
 
@@ -130,11 +130,11 @@ func.func @structured_cfg() {
 // CHECK:       Erasing block ^bb0 from region 0 from operation 'scf.for'
 
 // CHECK-LABEL: Op post-order erasures (no skip)
-// CHECK:       Erasing op 'use0'
-// CHECK:       Erasing op 'use1'
-// CHECK:       Erasing op 'use2'
+// CHECK:       Erasing op 'test.zero'
+// CHECK:       Erasing op 'test.one'
+// CHECK:       Erasing op 'test.two'
 // CHECK:       Erasing op 'scf.if'
-// CHECK:       Erasing op 'use3'
+// CHECK:       Erasing op 'test.three'
 // CHECK:       Erasing op 'scf.for'
 // CHECK:       Erasing op 'func.return'
 // CHECK:       Erasing op 'func.func'
@@ -150,15 +150,15 @@ func.func @structured_cfg() {
 // -----
 
 func.func @unstructured_cfg() {
-  "regionOp0"() ({
+  "test.regiontest.op0"() ({
     ^bb0:
-      "op0"() : () -> ()
+      "test.op0"() : () -> ()
       cf.br ^bb2
     ^bb1:
-      "op1"() : () -> ()
+      "test.op1"() : () -> ()
       cf.br ^bb2
     ^bb2:
-      "op2"() : () -> ()
+      "test.op2"() : () -> ()
   }) : () -> ()
   return
 }
@@ -166,138 +166,138 @@ func.func @unstructured_cfg() {
 // CHECK-LABEL: Op pre-order visits
 // CHECK:       Visiting op 'builtin.module'
 // CHECK:       Visiting op 'func.func'
-// CHECK:       Visiting op 'regionOp0'
-// CHECK:       Visiting op 'op0'
+// CHECK:       Visiting op 'test.regiontest.op0'
+// CHECK:       Visiting op 'test.op0'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op1'
+// CHECK:       Visiting op 'test.op1'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op2'
+// CHECK:       Visiting op 'test.op2'
 // CHECK:       Visiting op 'func.return'
 
 // CHECK-LABEL: Block pre-order visits
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'builtin.module'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'func.func'
-// CHECK:       Visiting block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb1 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb2 from region 0 from operation 'regionOp0'
+// CHECK:       Visiting block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb1 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb2 from region 0 from operation 'test.regiontest.op0'
 
 // CHECK-LABEL: Region pre-order visits
 // CHECK:       Visiting region 0 from operation 'builtin.module'
 // CHECK:       Visiting region 0 from operation 'func.func'
-// CHECK:       Visiting region 0 from operation 'regionOp0'
+// CHECK:       Visiting region 0 from operation 'test.regiontest.op0'
 
 // CHECK-LABEL: Op post-order visits
-// CHECK:       Visiting op 'op0'
+// CHECK:       Visiting op 'test.op0'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op1'
+// CHECK:       Visiting op 'test.op1'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op2'
-// CHECK:       Visiting op 'regionOp0'
+// CHECK:       Visiting op 'test.op2'
+// CHECK:       Visiting op 'test.regiontest.op0'
 // CHECK:       Visiting op 'func.return'
 // CHECK:       Visiting op 'func.func'
 // CHECK:       Visiting op 'builtin.module'
 
 // CHECK-LABEL: Block post-order visits
-// CHECK:       Visiting block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb1 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb2 from region 0 from operation 'regionOp0'
+// CHECK:       Visiting block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb1 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb2 from region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'func.func'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'builtin.module'
 
 // CHECK-LABEL: Region post-order visits
-// CHECK:       Visiting region 0 from operation 'regionOp0'
+// CHECK:       Visiting region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting region 0 from operation 'func.func'
 // CHECK:       Visiting region 0 from operation 'builtin.module'
 
 // CHECK-LABEL: Op reverse post-order visits
 // CHECK:       Visiting op 'func.return'
-// CHECK:       Visiting op 'op2'
+// CHECK:       Visiting op 'test.op2'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op1'
+// CHECK:       Visiting op 'test.op1'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op0'
-// CHECK:       Visiting op 'regionOp0'
+// CHECK:       Visiting op 'test.op0'
+// CHECK:       Visiting op 'test.regiontest.op0'
 // CHECK:       Visiting op 'func.func'
 // CHECK:       Visiting op 'builtin.module'
 
 // CHECK-LABEL: Block reverse post-order visits
-// CHECK:       Visiting block ^bb2 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb1 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb0 from region 0 from operation 'regionOp0'
+// CHECK:       Visiting block ^bb2 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb1 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb0 from region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'func.func'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'builtin.module'
 
 // CHECK-LABEL: Region reverse post-order visits
-// CHECK:       Visiting region 0 from operation 'regionOp0'
+// CHECK:       Visiting region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting region 0 from operation 'func.func'
 // CHECK:       Visiting region 0 from operation 'builtin.module'
 
 // CHECK-LABEL: Op pre-order erasures (skip)
-// CHECK:       Erasing op 'regionOp0'
+// CHECK:       Erasing op 'test.regiontest.op0'
 // CHECK:       Erasing op 'func.return'
 
 // CHECK-LABEL: Block pre-order erasures (skip)
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
 
 // CHECK-LABEL: Op post-order erasures (skip)
-// CHECK:       Erasing op 'op0'
+// CHECK:       Erasing op 'test.op0'
 // CHECK:       Erasing op 'cf.br'
-// CHECK:       Erasing op 'op1'
+// CHECK:       Erasing op 'test.op1'
 // CHECK:       Erasing op 'cf.br'
-// CHECK:       Erasing op 'op2'
-// CHECK:       Erasing op 'regionOp0'
+// CHECK:       Erasing op 'test.op2'
+// CHECK:       Erasing op 'test.regiontest.op0'
 // CHECK:       Erasing op 'func.return'
 
 // CHECK-LABEL: Block post-order erasures (skip)
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
 
 // CHECK-LABEL: Op post-order erasures (no skip)
-// CHECK:       Erasing op 'op0'
+// CHECK:       Erasing op 'test.op0'
 // CHECK:       Erasing op 'cf.br'
-// CHECK:       Erasing op 'op1'
+// CHECK:       Erasing op 'test.op1'
 // CHECK:       Erasing op 'cf.br'
-// CHECK:       Erasing op 'op2'
-// CHECK:       Erasing op 'regionOp0'
+// CHECK:       Erasing op 'test.op2'
+// CHECK:       Erasing op 'test.regiontest.op0'
 // CHECK:       Erasing op 'func.return'
 
 // CHECK-LABEL: Block post-order erasures (no skip)
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
 // CHECK:       Erasing block ^bb0 from region 0 from operation 'func.func'
 // CHECK:       Erasing block ^bb0 from region 0 from operation 'builtin.module'
 
 // -----
 
 func.func @unordered_cfg_with_loop() {
-  "regionOp0"() ({
+  "test.regiontest.op0"() ({
     ^bb0:
-      %c = "op0"() : () -> (i1)
+      %c = "test.op0"() : () -> (i1)
       cf.cond_br %c, ^bb2, ^bb3
     ^bb1:
-      "op1"(%val) : (i32) -> ()
+      "test.op1"(%val) : (i32) -> ()
       cf.br ^bb5
     ^bb2:
-      %val = "op2"() : () -> (i32)
+      %val = "test.op2"() : () -> (i32)
       cf.br ^bb1
     ^bb3:
-      "op3"() : () -> ()
+      "test.op3"() : () -> ()
       cf.br ^bb2
     ^bb4:
-      "op4"() : () -> ()
+      "test.op4"() : () -> ()
       cf.br ^bb2
     ^bb5:
-      "op5"() : () -> ()
+      "test.op5"() : () -> ()
       cf.br ^bb7
     ^bb6:
-      "op6"() : () -> ()
+      "test.op6"() : () -> ()
       cf.br ^bb6
     ^bb7:
-      "op7"() : () -> ()
+      "test.op7"() : () -> ()
   }) : () -> ()
   return
 }
@@ -314,71 +314,88 @@ func.func @unordered_cfg_with_loop() {
 //  3
 
 // CHECK-LABEL: Op forward dominance post-order visits
-// CHECK:       Visiting op 'op0'
+// CHECK:       Visiting op 'test.op0'
 // CHECK:       Visiting op 'cf.cond_br'
-// CHECK:       Visiting op 'op2'
+// CHECK:       Visiting op 'test.op2'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op1'
+// CHECK:       Visiting op 'test.op1'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op5'
+// CHECK:       Visiting op 'test.op5'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op7'
-// CHECK:       Visiting op 'op3'
+// CHECK:       Visiting op 'test.op7'
+// CHECK:       Visiting op 'test.op3'
 // CHECK:       Visiting op 'cf.br'
-// CHECK-NOT:   Visiting op 'op6'
-// CHECK:       Visiting op 'regionOp0'
+// CHECK-NOT:   Visiting op 'test.op6'
+// CHECK:       Visiting op 'test.regiontest.op0'
 // CHECK:       Visiting op 'func.return'
 // CHECK:       Visiting op 'func.func'
 
 // CHECK-LABEL: Block forward dominance post-order visits
-// CHECK:       Visiting block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb2 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb1 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb5 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb7 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb3 from region 0 from operation 'regionOp0'
+// CHECK:       Visiting block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb2 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb1 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb5 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb7 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb3 from region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'func.func'
 
 // CHECK-LABEL: Region forward dominance post-order visits
-// CHECK:       Visiting region 0 from operation 'regionOp0'
+// CHECK:       Visiting region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting region 0 from operation 'func.func'
 
 // CHECK-LABEL: Op reverse dominance post-order visits
 // CHECK:       Visiting op 'func.return'
-// CHECK-NOT:   Visiting op 'op6'
-// CHECK:       Visiting op 'op7'
+// CHECK-NOT:   Visiting op 'test.op6'
+// CHECK:       Visiting op 'test.op7'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op5'
+// CHECK:       Visiting op 'test.op5'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op1'
+// CHECK:       Visiting op 'test.op1'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op2'
+// CHECK:       Visiting op 'test.op2'
 // CHECK:       Visiting op 'cf.br'
-// CHECK:       Visiting op 'op3'
+// CHECK:       Visiting op 'test.op3'
 // CHECK:       Visiting op 'cf.cond_br'
-// CHECK:       Visiting op 'op0'
-// CHECK:       Visiting op 'regionOp0'
+// CHECK:       Visiting op 'test.op0'
+// CHECK:       Visiting op 'test.regiontest.op0'
 // CHECK:       Visiting op 'func.func'
 
 // CHECK-LABEL: Block reverse dominance post-order visits
-// CHECK:       Visiting block ^bb7 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb5 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb1 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb2 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb3 from region 0 from operation 'regionOp0'
-// CHECK:       Visiting block ^bb0 from region 0 from operation 'regionOp0'
+// CHECK:       Visiting block ^bb7 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb5 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb1 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb2 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb3 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Visiting block ^bb0 from region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting block ^bb0 from region 0 from operation 'func.func'
 
 // CHECK-LABEL: Region reverse dominance post-order visits
-// CHECK:       Visiting region 0 from operation 'regionOp0'
+// CHECK:       Visiting region 0 from operation 'test.regiontest.op0'
 // CHECK:       Visiting region 0 from operation 'func.func'
 
 // CHECK-LABEL: Block pre-order erasures (skip)
-// CHECK:       Erasing block ^bb0 from region 0 from operation 'regionOp0'
-// CHECK:       Cannot erase block ^bb0 from region 0 from operation 'regionOp0', still has uses
-// CHECK:       Cannot erase block ^bb1 from region 0 from operation 'regionOp0', still has uses
-// CHECK:       Erasing block ^bb2 from region 0 from operation 'regionOp0'
-// CHECK:       Erasing block ^bb2 from region 0 from operation 'regionOp0'
-// CHECK:       Cannot erase block ^bb2 from region 0 from operation 'regionOp0', still has uses
-// CHECK:       Cannot erase block ^bb3 from region 0 from operation 'regionOp0', still has uses
-// CHECK:       Cannot erase block ^bb4 from region 0 from operation 'regionOp0', still has uses
+// CHECK:       Erasing block ^bb0 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Cannot erase block ^bb0 from region 0 from operation 'test.regiontest.op0', still has uses
+// CHECK:       Cannot erase block ^bb1 from region 0 from operation 'test.regiontest.op0', still has uses
+// CHECK:       Erasing block ^bb2 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Erasing block ^bb2 from region 0 from operation 'test.regiontest.op0'
+// CHECK:       Cannot erase block ^bb2 from region 0 from operation 'test.regiontest.op0', still has uses
+// CHECK:       Cannot erase block ^bb3 from region 0 from operation 'test.regiontest.op0', still has uses
+// CHECK:       Cannot erase block ^bb4 from region 0 from operation 'test.regiontest.op0', still has uses
+
+// -----
+
+// The following test should not crash while visiting the intra-op blocks (inside the top level 
+// function in this case). We are testing that the intra-block ops are erased after dropping their
+// uses from the parent block holding op.
+// CHECK-LABEL: func.func @test_no_skip_block_erasure
+func.func @test_no_skip_block_erasure() {
+  %c0 = arith.constant 0 : index
+  %c3 = arith.constant 3 : index
+  cf.br ^bb1
+^bb1:
+  %cond = arith.cmpi eq, %c0, %c3 : index
+  cf.br ^bb4
+^bb4:
+  return
+}
diff --git a/mlir/test/lib/IR/TestVisitors.cpp b/mlir/test/lib/IR/TestVisitors.cpp
index 7df0ddb7ca27e..4a2a3fb5f8632 100644
--- a/mlir/test/lib/IR/TestVisitors.cpp
+++ b/mlir/test/lib/IR/TestVisitors.cpp
@@ -184,6 +184,24 @@ static void testNoSkipErasureCallbacks(Operation *op) {
       llvm::outs() << "Erasing ";
       printBlock(block);
       llvm::outs() << "\n";
+
+      // Only drop uses from oper...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/181320


More information about the Mlir-commits mailing list