27#include <llvm/ADT/STLExtras.h>
28#include <llvm/ADT/SmallVector.h>
29#include <llvm/Support/Debug.h>
31#define DEBUG_TYPE "poly-dialect-shared"
34 mlir::ConversionTarget target(*ctx);
35 target.addLegalDialect<
41 target.addLegalOp<mlir::ModuleOp>();
52 if (llvm::isa<llzk::component::StructDefOp>(op)) {
56 return !fdef.isInStruct();
67 for (mlir::SymbolRefAttr path : tryToErasePaths) {
68 LLVM_DEBUG(llvm::dbgs() <<
"[FromEraseSet] path to erase: " << path <<
'\n';);
69 mlir::Operation *lookupFrom =
rootMod.getOperation();
71 assert(mlir::succeeded(res) &&
"inputs must be valid symbol references");
73 if (!res->viaInclude()) {
74 mlir::SymbolOpInterface op = llvm::cast<mlir::SymbolOpInterface>(res->get());
75 LLVM_DEBUG(llvm::dbgs() <<
"[FromEraseSet] added op to the erase set: " << op <<
'\n';);
76 tryToErase.insert(op);
79 llvm::dbgs() <<
"[FromEraseSet] ignored op because it comes from an include: "
80 << res->get() <<
'\n';
88 for (mlir::SymbolOpInterface sym : tryToErase) {
89 collectSafeToErase(sym);
93 for (
auto &it : llvm::make_early_inc_range(visitedPlusSafetyResult)) {
94 if (!it.second || !tryToErase.contains(it.first)) {
95 visitedPlusSafetyResult.erase(it.first);
98 for (
auto &[sym, _] : visitedPlusSafetyResult) {
99 LLVM_DEBUG(llvm::dbgs() <<
"[EraseIfUnused] removing: " << sym.getNameAttr() <<
'\n');
102 return mlir::success();
105bool llzk::polymorphic::detail::FromEraseSet::collectSafeToErase(mlir::SymbolOpInterface
check) {
109 auto visited = visitedPlusSafetyResult.find(
check);
110 if (visited != visitedPlusSafetyResult.end()) {
111 return visited->second;
116 visitedPlusSafetyResult[
check] =
false;
122 visitedPlusSafetyResult[
check] =
true;
127 if (collectSafeToErase(defTree.lookupNode(
check))) {
128 const auto *useNode = useGraph.lookupNode(
check);
129 if (!useNode || collectSafeToErase(useNode)) {
135 visitedPlusSafetyResult[
check] =
false;
139bool llzk::polymorphic::detail::FromEraseSet::collectSafeToErase(
140 const llzk::SymbolDefTreeNode *
check
143 if (
const llzk::SymbolDefTreeNode *p =
check->getParent()) {
144 if (mlir::SymbolOpInterface checkOp = p->getOp()) {
145 return collectSafeToErase(checkOp);
151bool llzk::polymorphic::detail::FromEraseSet::collectSafeToErase(
152 const llzk::SymbolUseGraphNode *
check
155 for (
const llzk::SymbolUseGraphNode *p :
check->predecessorIter()) {
156 if (mlir::SymbolOpInterface checkOp = cachedLookup(p)) {
157 if (!collectSafeToErase(checkOp)) {
165mlir::SymbolOpInterface
166llzk::polymorphic::detail::FromEraseSet::cachedLookup(
const llzk::SymbolUseGraphNode *node) {
167 assert(node &&
"must provide a node");
169 auto fromCache = lookupCache.find(node);
170 if (fromCache != lookupCache.end()) {
171 return fromCache->second;
175 assert(mlir::succeeded(lookupRes) &&
"graph contains node with invalid path");
176 assert(lookupRes->get() !=
nullptr &&
"lookup must return an Operation");
181 mlir::SymbolOpInterface actualRes =
182 lookupRes->viaInclude() ? nullptr : llvm::cast<mlir::SymbolOpInterface>(lookupRes->get());
184 lookupCache[node] = actualRes;
185 assert((!actualRes == lookupRes->viaInclude()) &&
"not found iff included");
193 while (
auto nestedArrTy = llvm::dyn_cast<llzk::array::ArrayType>(convertedElemTy)) {
194 llvm::append_range(mergedDims, nestedArrTy.getDimensionSizes());
195 convertedElemTy = nestedArrTy.getElementType();
Common private implementation for poly dialect passes.
This file defines methods symbol lookup across LLZK operations and included files.
Builds a tree structure representing the symbol table structure.
mlir::FailureOr< SymbolLookupResultUntyped > lookupSymbol(mlir::SymbolTableCollection &tables, bool reportMissing=true) const
Builds a graph structure representing the relationships between symbols and their uses.
static ArrayType get(::mlir::Type elementType, ::llvm::ArrayRef<::mlir::Attribute > dimensionSizes)
::llvm::ArrayRef<::mlir::Attribute > getDimensionSizes() const
const SymbolDefTree & defTree
const SymbolUseGraph & useGraph
mlir::SymbolTableCollection tables
CleanupBase(mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph)
mlir::LogicalResult eraseUnusedDefinitions()
FromEraseSet(mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph, llvm::DenseSet< mlir::SymbolRefAttr > &&tryToErasePaths)
Note: paths in tryToErase should be relative to root.
bool isErasableDefinition(mlir::Operation *op)
Return true iff op is a cleanup candidate.
mlir::ConversionTarget newBaseTarget(mlir::MLIRContext *ctx)
Return a new ConversionTarget allowing all LLZK-required dialects.
array::ArrayType flattenInstantiatedArrayType(array::ArrayType inputTy, mlir::Type convertedElemTy)
Merge nested array dimensions produced by replacing an array element type.
mlir::FailureOr< SymbolLookupResultUntyped > lookupSymbolIn(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, Within &&lookupWithin, mlir::Operation *origin, bool reportMissing=true)