[Mlir-commits] [mlir] [mlir] Refactor transform.apply_dce into a eliminateTriviallyDeadOps region-utils helper (PR #194041)

Hocky Yudhiono llvmlistbot at llvm.org
Tue Apr 28 20:28:24 PDT 2026


================
@@ -506,6 +507,78 @@ LogicalResult mlir::runRegionDCE(RewriterBase &rewriter,
   return deleteDeadness(rewriter, regions, liveMap);
 }
 
+bool mlir::eliminateTriviallyDeadOps(RewriterBase &rewriter, Region &region,
+                                     bool includeNestedRegions) {
+  bool changed = false;
+
+  // Step 1: walk each op in reverse program order. If the op is already
+  // trivially dead, erase it outright — there's no point recursing into
+  // regions that will be destroyed with it. Otherwise, if
+  // `includeNestedRegions` is set, recurse into its nested regions so values
+  // defined in `region` may lose their last user and show up as dead in
+  // step 2's seed. Reverse iteration lets dead chains propagate within this
+  // single pass.
+  for (Block &block : llvm::reverse(region)) {
+    for (Operation &op :
+         llvm::make_early_inc_range(llvm::reverse(block.getOperations()))) {
+      if (isOpTriviallyDead(&op)) {
+        rewriter.eraseOp(&op);
+        changed = true;
+        continue;
+      }
+      if (includeNestedRegions)
+        for (Region &nested : op.getRegions())
+          changed |= eliminateTriviallyDeadOps(rewriter, nested);
+    }
+  }
+
+  // Step 2: worklist over ops in this region only.
+  //
+  // Worklist invariant: an op is pushed *only* once we have verified it is
+  // trivially dead. No speculative enqueues — every op on the worklist will
+  // be erased when popped. Two things enforce this:
+  //   - the initial seed below calls isOpTriviallyDead before enqueueing,
+  //   - the propagation inside the loop drops the erasing op's use of
+  //     `defOp` *before* re-checking isOpTriviallyDead(defOp), so the check
+  //     sees the post-erase use count and only enqueues when actually dead.
+  // Deadness is monotonic within this pass (we never add users, only remove
+  // them), so an op that was dead at enqueue time is still dead at pop time.
+  // The `inWorklist` set is just for dedup; no re-check is needed on pop.
+  SmallVector<Operation *> worklist;
----------------
hockyy wrote:

nit: Can Use `SmallSetVector` or `SetVector` here and remove the `enqueue` function.

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


More information about the Mlir-commits mailing list