Introduce a lightweight, targeted dead-op eliminator that complements the existing liveness-based runRegionDCE. The algorithm is O(ops): step 1 walks each op in reverse program order, erases it outright if trivially dead, or recurses into nested regions when recursive cleanup is enabled; step 2 drives a per-region worklist that only ever holds ops already verified dead, propagating new deadness by dropping each operand's use before re-checking isOpTriviallyDead on the defining op. Unlike runRegionDCE, this does not touch dead block arguments, dead successor operands, or dead use-def cycles. Use runRegionDCE when those are required. An includeNestedRegions parameter lets callers restrict simplification to the top-level region. Switch transform.apply_dce to use the new helper, dropping a custom worklist that had subtle invariants: SetVector dedup, linear search on every erase, and pre-order walk with skip. In general it is bad practice to implement complex custom logic in Transform ops apply methods: this should be an adaptor exposing MLIR transformations to the transform dialect; non-trivial logic deserves a public API for reusability and proper layering. Introduce a TrivialDeadCodeEliminationPass exposed as -trivial-dce. The pass removes trivially dead operations and, when removeBlocks is enabled, unreachable blocks. It does not run liveness analysis and does not remove dead use-def cycles. Add recursive and removeBlocks options, both defaulting to true, to control whether nested regions are visited and whether unreachable blocks are erased. Assisted-by: Claude Code
38 lines
1.2 KiB
C++
38 lines
1.2 KiB
C++
//===- TrivialDeadCodeElimination.cpp - Trivial DCE -----------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/IR/Operation.h"
|
|
#include "mlir/Pass/Pass.h"
|
|
#include "mlir/Transforms/Passes.h"
|
|
#include "mlir/Transforms/RegionUtils.h"
|
|
|
|
namespace mlir {
|
|
#define GEN_PASS_DEF_TRIVIALDEADCODEELIMINATIONPASS
|
|
#include "mlir/Transforms/Passes.h.inc"
|
|
} // namespace mlir
|
|
|
|
using namespace mlir;
|
|
|
|
namespace {
|
|
struct TrivialDeadCodeElimination
|
|
: public impl::TrivialDeadCodeEliminationPassBase<
|
|
TrivialDeadCodeElimination> {
|
|
using impl::TrivialDeadCodeEliminationPassBase<
|
|
TrivialDeadCodeElimination>::TrivialDeadCodeEliminationPassBase;
|
|
|
|
void runOnOperation() override {
|
|
Operation *target = getOperation();
|
|
IRRewriter rewriter(target->getContext());
|
|
if (removeBlocks)
|
|
(void)eraseUnreachableBlocks(rewriter, target->getRegions(), recursive);
|
|
for (Region ®ion : target->getRegions())
|
|
eliminateTriviallyDeadOps(rewriter, region, recursive);
|
|
}
|
|
};
|
|
} // namespace
|