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

Prathamesh Tagore llvmlistbot at llvm.org
Tue Feb 17 02:17:37 PST 2026


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

>From d158e2ba458610139a9489c853f8434dd049fa0b Mon Sep 17 00:00:00 2001
From: Prathamesh Tagore <prathameshtagore at gmail.com>
Date: Mon, 16 Feb 2026 21:09:14 +0100
Subject: [PATCH 1/2] [NFC][test-ir-visitors] Remove unregistered dialect uses
 from tests

Use the already registered test dialect in tests which is explicitly intended
to allow arbitrary ops.
---
 mlir/test/IR/visitors.mlir | 236 ++++++++++++++++++-------------------
 1 file changed, 118 insertions(+), 118 deletions(-)

diff --git a/mlir/test/IR/visitors.mlir b/mlir/test/IR/visitors.mlir
index ec7712a45d388..a60f9e0afa0d8 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,71 @@ 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

>From 9f73d2ebf59876225c8be7a8aa810004e50fe52a Mon Sep 17 00:00:00 2001
From: Prathamesh Tagore <prathameshtagore at gmail.com>
Date: Mon, 16 Feb 2026 21:31:09 +0100
Subject: [PATCH 2/2] [mlir][test-ir-visitors] Fix erasure of operations with
 intact uses

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 case where
the current block might be providing global context to other blocks in the
same parent region 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 intra-block op uses from ops within the same parent
region.
---
 mlir/test/IR/visitors.mlir        | 17 +++++++++++++++++
 mlir/test/lib/IR/TestVisitors.cpp | 18 ++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/mlir/test/IR/visitors.mlir b/mlir/test/IR/visitors.mlir
index a60f9e0afa0d8..104ebac976cf9 100644
--- a/mlir/test/IR/visitors.mlir
+++ b/mlir/test/IR/visitors.mlir
@@ -382,3 +382,20 @@ func.func @unordered_cfg_with_loop() {
 // 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 ops with same parent region.
+// 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..2667001ee10a7 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 operations within the same parent region. This
+      // avoids erasing operations with their uses still intact and eliminates
+      // such crashes.
+      // Note: We do not drop the use when the parent region is different for
+      // it, because this means that the use's region holding op is a child of
+      // the region holding op containing the current block and was expected to
+      // be visited and erased first - we should correctly fail here.
+      Region *blockParentRegion = block->front().getParentRegion();
+      for (Operation &op : *block) {
+        for (OpOperand &use : llvm::make_early_inc_range(op.getUses())) {
+          // Early continue if the parent regions are not same.
+          if (blockParentRegion != use.getOwner()->getParentRegion())
+            continue;
+          use.drop();
+        }
+      }
+
       block->erase();
     } else {
       llvm::outs() << "Cannot erase ";



More information about the Mlir-commits mailing list