CIRCT 23.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 return op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName());
76}
77
79 root->walk([&](Operation *op) {
80 auto collect = [&](Attribute attr) {
81 if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr))
82 symbolRefs.insert(symbolRef.getAttr());
83
84 if (auto innerRef = dyn_cast<hw::InnerRefAttr>(attr)) {
85 innerRefs.insert({innerRef.getModule(), innerRef.getName()});
86 innerRefModules.insert(innerRef.getModule());
87 }
88 };
89 for (auto namedAttr : op->getAttrs())
90 namedAttr.getValue().walk(collect);
91 for (auto result : op->getResults())
92 result.getType().walk(collect);
93 for (auto &region : op->getRegions())
94 for (auto &block : region)
95 for (auto arg : block.getArguments())
96 arg.getType().walk(collect);
97 });
98}
99
100bool InnerSymbolUses::hasInnerRef(Operation *op) const {
101 if (auto symbol = getSymbolName(op))
102 return hasInnerRef(symbol);
103
104 if (auto innerSym = hw::InnerSymbolTable::getInnerSymbol(op)) {
105 StringAttr symbol;
106 auto *parent = op->getParentOp();
107 while (parent && !(symbol = getSymbolName(parent)))
108 parent = parent->getParentOp();
109 if (symbol)
110 return hasInnerRef(symbol, innerSym);
111 }
112
113 return false;
114}
115
116bool InnerSymbolUses::hasInnerRef(hw::InnerRefAttr innerRef) const {
117 return innerRefs.contains({innerRef.getModule(), innerRef.getName()});
118}
119
120bool InnerSymbolUses::hasInnerRef(StringAttr symbol) const {
121 return innerRefModules.contains(symbol);
122}
123
124bool InnerSymbolUses::hasInnerRef(StringAttr symbol,
125 StringAttr innerSym) const {
126 return innerRefs.contains({symbol, innerSym});
127}
128
129bool InnerSymbolUses::hasSymbolRef(Operation *op) const {
130 return symbolRefs.contains(getSymbolName(op));
131}
132
133bool InnerSymbolUses::hasSymbolRef(StringAttr symbol) const {
134 return symbolRefs.contains(symbol);
135}
136
137bool InnerSymbolUses::hasRef(Operation *op) const {
138 return hasInnerRef(op) || hasSymbolRef(op);
139}
140
141bool InnerSymbolUses::hasRef(StringAttr symbol) const {
142 return hasInnerRef(symbol) || hasSymbolRef(symbol);
143}
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:87
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.