CIRCT 24.0.0git
Loading...
Searching...
No Matches
ReductionUtils.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
12#include "mlir/IR/Operation.h"
13#include "llvm/ADT/SmallSet.h"
14
15using namespace circt;
16using namespace circt::reduce;
17
18//===----------------------------------------------------------------------===//
19// MetasyntacticNameGenerator
20//===----------------------------------------------------------------------===//
21
23 if (index >= std::size(names))
24 index = 0;
25 return names[index++];
26}
27
31
33 // Build a set of all metasyntactic names on first use.
34 static const llvm::StringSet<> nameSet = [] {
35 llvm::StringSet<> s;
36 for (auto *n : names)
37 s.insert(n);
38 return s;
39 }();
40 // The prefix is everything before the first '_', or the whole name.
41 return nameSet.contains(name.split('_').first);
42}
43
44//===----------------------------------------------------------------------===//
45// Utilities
46//===----------------------------------------------------------------------===//
47
48void reduce::pruneUnusedOps(SmallVectorImpl<Operation *> &worklist,
49 Reduction &reduction) {
51 while (!worklist.empty()) {
52 auto *op = worklist.pop_back_val();
53 if (!op || handled.contains(op) || !op->use_empty() ||
54 op->hasAttr("inner_sym"))
55 continue;
56 handled.insert(op);
57 for (auto arg : op->getOperands())
58 if (auto *argOp = arg.getDefiningOp())
59 worklist.push_back(argOp);
60 reduction.notifyOpErased(op);
61 op->erase();
62 }
63}
64
65void reduce::pruneUnusedOps(Operation *initialOp, Reduction &reduction) {
66 SmallVector<Operation *> worklist({initialOp});
67 pruneUnusedOps(worklist, reduction);
68}
69
70//===----------------------------------------------------------------------===//
71// InnerSymbolUses
72//===----------------------------------------------------------------------===//
73
74static StringAttr getSymbolName(Operation *op) {
75 if (auto symbol = dyn_cast<mlir::SymbolOpInterface>(op))
76 return symbol.getNameAttr();
77 return {};
78}
79
81 root->walk([&](Operation *op) {
82 auto collect = [&](Attribute attr) {
83 if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr))
84 symbolRefs.insert(symbolRef.getAttr());
85
86 if (auto innerRef = dyn_cast<hw::InnerRefAttr>(attr)) {
87 innerRefs.insert({innerRef.getModule(), innerRef.getName()});
88 innerRefModules.insert(innerRef.getModule());
89 }
90 };
91 for (auto namedAttr : op->getAttrs())
92 namedAttr.getValue().walk(collect);
93 for (auto result : op->getResults())
94 result.getType().walk(collect);
95 for (auto &region : op->getRegions())
96 for (auto &block : region)
97 for (auto arg : block.getArguments())
98 arg.getType().walk(collect);
99 });
100}
101
102bool InnerSymbolUses::hasInnerRef(Operation *op) const {
103 if (auto symbol = getSymbolName(op))
104 return hasInnerRef(symbol);
105
106 if (auto innerSym = hw::InnerSymbolTable::getInnerSymbol(op)) {
107 StringAttr symbol;
108 auto *parent = op->getParentOp();
109 while (parent && !(symbol = getSymbolName(parent)))
110 parent = parent->getParentOp();
111 if (symbol)
112 return hasInnerRef(symbol, innerSym);
113 }
114
115 return false;
116}
117
118bool InnerSymbolUses::hasInnerRef(hw::InnerRefAttr innerRef) const {
119 return innerRefs.contains({innerRef.getModule(), innerRef.getName()});
120}
121
122bool InnerSymbolUses::hasInnerRef(StringAttr symbol) const {
123 return innerRefModules.contains(symbol);
124}
125
126bool InnerSymbolUses::hasInnerRef(StringAttr symbol,
127 StringAttr innerSym) const {
128 return innerRefs.contains({symbol, innerSym});
129}
130
131bool InnerSymbolUses::hasSymbolRef(Operation *op) const {
132 return symbolRefs.contains(getSymbolName(op));
133}
134
135bool InnerSymbolUses::hasSymbolRef(StringAttr symbol) const {
136 return symbolRefs.contains(symbol);
137}
138
139bool InnerSymbolUses::hasRef(Operation *op) const {
140 return hasInnerRef(op) || hasSymbolRef(op);
141}
142
143bool InnerSymbolUses::hasRef(StringAttr symbol) const {
144 return hasInnerRef(symbol) || hasSymbolRef(symbol);
145}
static StringAttr getSymbolName(Operation *op)
A namespace that is used to store existing names and generate new names in some scope within the IR.
Definition Namespace.h:30
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
Definition Namespace.h:86
static StringAttr getInnerSymbol(Operation *op)
Get InnerSymbol for an operation.
static bool isMetasyntacticName(StringRef name)
Return true if name already has a metasyntactic prefix, i.e.
const char * getNextName()
Get the next metasyntactic name in the sequence.
static constexpr const char * names[48]
void pruneUnusedOps(SmallVectorImpl< Operation * > &worklist, Reduction &reduction)
Starting from an initial worklist of operations, traverse through it and its operands and erase opera...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
An abstract reduction pattern.
Definition Reduction.h:24
void notifyOpErased(Operation *op)
Definition Reduction.h:101
DenseSet< StringAttr > innerRefModules
Symbol names used in inner refs.
bool hasSymbolRef(Operation *op) const
Check whether the given symbol is targeted by a symbol ref.
bool hasInnerRef(Operation *op) const
Check whether an op is targeted by an inner ref.
DenseSet< StringAttr > symbolRefs
Symbol names used in symbol or inner refs.
bool hasRef(Operation *op) const
Check whether the given symbol is targeted by a symbol ref or inner ref.
DenseSet< std::pair< StringAttr, StringAttr > > innerRefs
Symbol and inner symbol name pairs used in inner refs.