[Mlir-commits] [flang] [mlir] [mlir][CSE] Add pruneDeadOps to CSE pass (PR #191394)
lonely eagle
llvmlistbot at llvm.org
Sun Apr 12 09:17:37 PDT 2026
================
@@ -388,7 +390,45 @@ void CSEDriver::simplifyRegion(ScopedMapTy &knownValues, Region ®ion) {
}
}
+void CSEDriver::pruneDeadOps(Operation *op) {
+ SmallVector<Operation *> deadOps;
+ op->walk([&](Operation *op) {
+ if (isOpTriviallyDead(op))
+ deadOps.push_back(op);
+ });
+
+ // Use an erased set to avoid double erasure. An operand may be used
+ // multiple times by same dead ops, causing the same defining op
+ // to be added to the worklist more than once. The erased set guards
+ // against processing the same op twice.
+ DenseSet<Operation *> erased;
+ for (Operation *op : deadOps) {
+ SmallVector<Operation *> worklist;
+ worklist.push_back(op);
+ while (!worklist.empty()) {
+ Operation *op = worklist.pop_back_val();
+ if (erased.contains(op))
+ continue;
+ if (!isOpTriviallyDead(op))
+ continue;
+ for (Value arg : op->getOperands())
+ if (Operation *argOp = arg.getDefiningOp())
+ worklist.push_back(argOp);
+ erased.insert(op);
+ rewriter.eraseOp(op);
+ ++numDCE;
+ }
+ }
+}
+
void CSEDriver::simplify(Operation *op, bool *changed) {
+ /// Eagerly erase trivially dead operations to prevent them from interfering
+ /// with the CSE pass. Retaining dead operations in a region can affect the
+ /// equivalence check between two region ops, causing CSE to miss
+ /// optimization opportunities, and may also trigger unnecessary calls to
+ /// simplifyRegion on dead region ops.
+ pruneDeadOps(op);
----------------
linuxlonelyeagle wrote:
```
func.func @cse_dead_ops(%arg0: i1) {
%c0_i32 = arith.constant 0 : i32
%0 = arith.select %arg0, %c0_i32, %c0_i32 : i32
%1 = scf.if %arg0 -> (i32) {
%c0_i32_0 = arith.constant 0 : i32
scf.yield %c0_i32_0 : i32
} else {
%c0_i32_0 = arith.constant 0 : i32
scf.yield %c0_i32_0 : i32
}
return
}
```
it run cse, would be
```
func.func @cse_dead_ops(%arg0: i1) {
%c0_i32 = arith.constant 0 : i32
return
}
```
then I run canonicalization, it would be
```
func.func @cse_dead_ops(%arg0: i1) {
return
}
```
Overall, running canonicalization beforehand ensures that CSE remains highly effective. To be honest, I feel that CSE’s approach to removing dead ops is somewhat lacking, as it doesn't fully cover that functionality—though it doesn't seem to be a major issue.
https://github.com/llvm/llvm-project/pull/191394
More information about the Mlir-commits
mailing list