[Mlir-commits] [mlir] [mlir] Fix non-termination when a block becomes unreachable during rewriting (PR #221152)

Matthias Springer llvmlistbot at llvm.org
Sat Sep 5 08:58:43 PDT 2026


matthias-springer wrote:

Can you try something like this? I believe the worklist-based IR walk from #221037 is not necessary.
```
--- a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp
+++ b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp
@@ -166,12 +166,14 @@ simplifyBrToBlockWithSinglePred(BranchOp op, PatternRewriter &rewriter) {
   if (succ == opParent || !llvm::hasSingleElement(succ->getPredecessors()))
     return failure();
 
-  // If any branch operand is itself a block argument of the successor, merging
-  // would call replaceAllUsesWith(arg, arg) — a no-op — leaving dangling uses
-  // of that argument after the successor block is erased.
-  for (Value operand : op.getOperands())
-    if (auto ba = dyn_cast<BlockArgument>(operand))
-      if (ba.getOwner() == succ)
+  // Merging replaces the successor's arguments with this branch's operands. If
+  // an argument is already used in the predecessor, that replacement feeds a
+  // value derived from the argument back into its own uses: either a no-op
+  // replaceAllUsesWith(arg, arg) that leaves the argument live after the block
+  // is erased, or a self-referential op such as `%0 = arith.addi %0, %c1`.
+  for (BlockArgument arg : succ->getArguments())
+    for (Operation *user : arg.getUsers())
+      if (user->getBlock() == opParent)
         return failure();
 
   // Merge the successor into the current block and erase the branch.
```


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


More information about the Mlir-commits mailing list