17#include "mlir/IR/IRMapping.h"
18#include "llvm/Support/Debug.h"
22#define GEN_PASS_DEF_INLINESEQUENCESPASS
23#include "circt/Dialect/RTG/Transforms/RTGPasses.h.inc"
31#define DEBUG_TYPE "rtg-inline-sequences"
38struct InlineSequencesPass
39 :
public rtg::impl::InlineSequencesPassBase<InlineSequencesPass> {
42 void runOnOperation()
override;
47enum class DeletionKind { Delete, Keep };
51 :
public RTGOpVisitor<SequenceInliner, FailureOr<DeletionKind>> {
52 using RTGOpVisitor<SequenceInliner, FailureOr<DeletionKind>>::visitOp;
54 SequenceInliner(ModuleOp moduleOp) : table(moduleOp) {}
56 LogicalResult inlineSequences(TestOp testOp);
57 void materializeInterleavedSequence(Value value, ArrayRef<Block *> blocks,
62 FailureOr<DeletionKind> visitOp(InterleaveSequencesOp op) {
63 SmallVector<Block *> blocks;
64 for (
auto [i,
seq] : llvm::enumerate(op.getSequences())) {
65 auto iter = materializedSequences.find(
seq);
66 if (iter == materializedSequences.end())
67 return op->emitError()
68 <<
"sequence operand #" << i
69 <<
" could not be resolved; it was likely produced by an op or "
70 "block argument not supported by this pass";
72 blocks.push_back(iter->getSecond().first);
75 LLVM_DEBUG(llvm::dbgs()
76 <<
" - Computing sequence interleaving: " << op <<
"\n");
78 materializeInterleavedSequence(op.getInterleavedSequence(), blocks,
80 return DeletionKind::Delete;
83 FailureOr<DeletionKind> visitOp(GetSequenceOp op) {
84 auto seqOp = table.lookup<SequenceOp>(op.getSequenceAttr());
86 return op->emitError() <<
"referenced sequence not found";
88 LLVM_DEBUG(llvm::dbgs() <<
" - Registering existing sequence: "
89 << op.getSequence() <<
"\n");
91 materializedSequences[op.getResult()] =
92 std::make_pair(seqOp.getBody(), IRMapping());
93 return DeletionKind::Delete;
96 FailureOr<DeletionKind> visitOp(SubstituteSequenceOp op) {
97 LLVM_DEBUG(llvm::dbgs() <<
" - Substitute sequence: " << op <<
"\n");
99 auto iter = materializedSequences.find(op.getSequence());
100 if (iter == materializedSequences.end())
101 return op->emitError() <<
"sequence operand could not be resolved; it "
102 "was likely produced by an op or block "
103 "argument not supported by this pass";
105 IRMapping mapping = iter->getSecond().second;
106 Block *block = iter->getSecond().first;
107 for (
auto [arg, repl] :
108 llvm::zip(block->getArguments(), op.getReplacements())) {
109 LLVM_DEBUG(llvm::dbgs()
110 <<
" - Mapping " << arg <<
" to " << repl <<
"\n");
111 mapping.map(arg, repl);
114 materializedSequences[op.getResult()] = std::make_pair(block, mapping);
115 return DeletionKind::Delete;
118 FailureOr<DeletionKind> visitOp(RandomizeSequenceOp op) {
119 LLVM_DEBUG(llvm::dbgs() <<
" - Randomize sequence: " << op <<
"\n");
121 auto iter = materializedSequences.find(op.getSequence());
122 if (iter == materializedSequences.end())
123 return op->emitError() <<
"sequence operand could not be resolved; it "
124 "was likely produced by an op or block "
125 "argument not supported by this pass";
129 auto value = iter->getSecond();
130 materializedSequences[op.getResult()] = value;
131 return DeletionKind::Delete;
134 FailureOr<DeletionKind> visitOp(EmbedSequenceOp op) {
135 LLVM_DEBUG(llvm::dbgs() <<
" - Inlining sequence: " << op <<
"\n");
137 auto iter = materializedSequences.find(op.getSequence());
138 if (iter == materializedSequences.end())
139 return op->emitError() <<
"sequence operand could not be resolved; it "
140 "was likely produced by an op or block "
141 "argument not supported by this pass";
143 OpBuilder builder(op);
144 builder.setInsertionPointAfter(op);
145 IRMapping mapping = iter->getSecond().second;
148 for (
auto [k, v] : mapping.getValueMap())
149 llvm::dbgs() <<
" - Maps " << k <<
" to " << v <<
"\n";
152 for (
auto &op : *iter->getSecond().first) {
153 Operation *o = builder.clone(op, mapping);
155 LLVM_DEBUG(llvm::dbgs() <<
" - Inlined " << *o <<
"\n");
158 ++numSequencesInlined;
160 return DeletionKind::Delete;
164 return DeletionKind::Keep;
168 return DeletionKind::Keep;
172 DenseMap<Value, std::pair<Block *, IRMapping>> materializedSequences;
173 SmallVector<std::unique_ptr<Block>> blockStorage;
174 size_t numSequencesInlined = 0;
175 size_t numSequencesInterleaved = 0;
180void SequenceInliner::materializeInterleavedSequence(Value value,
181 ArrayRef<Block *> blocks,
182 uint32_t batchSize) {
183 auto *interleavedBlock =
184 blockStorage.emplace_back(std::make_unique<Block>()).get();
186 OpBuilder builder(value.getContext());
187 builder.setInsertionPointToStart(interleavedBlock);
189 SmallVector<Block::iterator> iters(blocks.size());
190 for (
auto [i, block] :
llvm::enumerate(blocks))
191 iters[i] = block->begin();
193 llvm::BitVector finishedBlocks(blocks.size());
194 for (
unsigned i = 0; !finishedBlocks.all(); i = (i + 1) % blocks.size()) {
195 if (finishedBlocks[i])
197 for (
unsigned k = 0; k < batchSize;) {
198 if (iters[i] == blocks[i]->
end()) {
199 finishedBlocks.set(i);
202 auto *op = builder.clone(*iters[i], mapping);
203 if (isa<InstructionOpInterface>(op))
209 materializedSequences[value] = std::make_pair(interleavedBlock, IRMapping());
210 numSequencesInterleaved += blocks.size();
213LogicalResult SequenceInliner::inlineSequences(TestOp testOp) {
214 LLVM_DEBUG(llvm::dbgs() <<
"\n=== Processing test @" << testOp.getSymName()
217 SmallVector<Operation *> toDelete;
218 for (
auto &op : *testOp.getBody()) {
219 auto result = dispatchOpVisitor(&op);
223 if (*result == DeletionKind::Delete)
224 toDelete.push_back(&op);
227 for (
auto *op :
llvm::reverse(toDelete))
233void InlineSequencesPass::runOnOperation() {
234 auto moduleOp = getOperation();
235 SequenceInliner inliner(moduleOp);
238 for (
auto testOp : moduleOp.getOps<TestOp>())
239 if (failed(inliner.inlineSequences(testOp)))
240 return signalPassFailure();
242 numSequencesInlined = inliner.numSequencesInlined;
243 numSequencesInterleaved = inliner.numSequencesInterleaved;
This helps visit TypeOp nodes.
ResultType visitExternalOp(Operation *op, ExtraArgs... args)
ResultType visitUnhandledOp(Operation *op, ExtraArgs... args)
This callback is invoked on any operations that are not handled by the concrete visitor.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.