18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/DebugLog.h"
20 #include "llvm/Support/InterleavedRange.h"
23 #define GEN_PASS_DEF_SYMBOLDCE
24 #include "mlir/Transforms/Passes.h.inc"
29 #define DEBUG_TYPE "symbol-dce"
32 struct SymbolDCE :
public impl::SymbolDCEBase<SymbolDCE> {
33 void runOnOperation()
override;
38 LogicalResult computeLiveness(
Operation *symbolTableOp,
40 bool symbolTableIsHidden,
45 void SymbolDCE::runOnOperation() {
46 Operation *symbolTableOp = getOperation();
51 <<
" was scheduled to run under SymbolDCE, but does not define a "
53 return signalPassFailure();
58 bool symbolTableIsHidden =
true;
59 SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(symbolTableOp);
61 symbolTableIsHidden = symbol.isPrivate();
66 if (
failed(computeLiveness(symbolTableOp, symbolTable, symbolTableIsHidden,
68 return signalPassFailure();
75 for (
auto &block : nestedSymbolTable->
getRegion(0)) {
76 for (Operation &op : llvm::make_early_inc_range(block)) {
77 if (isa<SymbolOpInterface>(&op) && !liveSymbols.count(&op)) {
89 LogicalResult SymbolDCE::computeLiveness(
Operation *symbolTableOp,
91 bool symbolTableIsHidden,
93 LDBG() <<
"computeLiveness: "
100 for (
auto &block : symbolTableOp->
getRegion(0)) {
103 SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(&op);
105 worklist.push_back(&op);
108 bool isDiscardable = (symbolTableIsHidden || symbol.isPrivate()) &&
109 symbol.canDiscardOnUseEmpty();
110 if (!isDiscardable && liveSymbols.insert(&op).second)
111 worklist.push_back(&op);
120 while (!worklist.empty()) {
122 LDBG() <<
"processing: "
129 SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op);
130 bool symIsHidden = symbolTableIsHidden || !symbol || symbol.isPrivate();
131 LDBG() <<
"\tsymbol table: "
133 <<
" is hidden: " << symIsHidden;
134 if (
failed(computeLiveness(op, symbolTable, symIsHidden, liveSymbols)))
137 LDBG() <<
"\tnon-symbol table: "
146 for (
auto &block : region.getBlocks())
149 worklist.push_back(&op);
160 std::optional<SymbolTable::UseRange> uses = SymbolTable::getSymbolUses(op);
163 <<
"operation contains potentially unknown symbol table, meaning "
164 <<
"that we can't reliable compute symbol uses";
170 LDBG() <<
"\tuse: " << use.getUser();
172 resolvedSymbols.clear();
177 LDBG() <<
"\t\tresolved symbols: "
178 << llvm::interleaved(resolvedSymbols,
", ");
181 for (
Operation *resolvedSymbol : resolvedSymbols)
182 if (liveSymbols.insert(resolvedSymbol).second)
183 worklist.push_back(resolvedSymbol);
191 return std::make_unique<SymbolDCE>();
Set of flags used to control the behavior of the various IR print methods (e.g.
A trait used to provide symbol table functionalities to a region operation.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
unsigned getNumRegions()
Returns the number of regions held by this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class represents a collection of SymbolTables.
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
This class represents a specific symbol use.
Include the generated interface declarations.
std::unique_ptr< Pass > createSymbolDCEPass()
Creates a pass which delete symbol operations that are unreachable.