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 *block = materializedSequences.lookup(
seq);
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(block);
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()] = seqOp.getBody();
92 return DeletionKind::Delete;
95 FailureOr<DeletionKind> visitOp(RandomizeSequenceOp op) {
96 LLVM_DEBUG(llvm::dbgs() <<
" - Randomize sequence: " << op <<
"\n");
98 auto *block = materializedSequences.lookup(op.getSequence());
100 return op->emitError() <<
"sequence operand could not be resolved; it "
101 "was likely produced by an op or block "
102 "argument not supported by this pass";
104 materializedSequences[op.getResult()] = block;
105 return DeletionKind::Delete;
108 FailureOr<DeletionKind> visitOp(EmbedSequenceOp op) {
109 LLVM_DEBUG(llvm::dbgs() <<
" - Inlining sequence: " << op <<
"\n");
111 auto *block = materializedSequences.lookup(op.getSequence());
113 return op->emitError() <<
"sequence operand could not be resolved; it "
114 "was likely produced by an op or block "
115 "argument not supported by this pass";
117 OpBuilder builder(op);
118 builder.setInsertionPointAfter(op);
120 for (
auto &op : *block)
121 builder.clone(op, mapping);
123 ++numSequencesInlined;
125 return DeletionKind::Delete;
129 return DeletionKind::Keep;
133 return DeletionKind::Keep;
137 DenseMap<Value, Block *> materializedSequences;
138 SmallVector<std::unique_ptr<Block>> blockStorage;
139 size_t numSequencesInlined = 0;
140 size_t numSequencesInterleaved = 0;
145void SequenceInliner::materializeInterleavedSequence(Value value,
146 ArrayRef<Block *> blocks,
147 uint32_t batchSize) {
148 auto *interleavedBlock =
149 blockStorage.emplace_back(std::make_unique<Block>()).get();
151 OpBuilder builder(value.getContext());
152 builder.setInsertionPointToStart(interleavedBlock);
154 SmallVector<Block::iterator> iters(blocks.size());
155 for (
auto [i, block] :
llvm::enumerate(blocks))
156 iters[i] = block->begin();
158 llvm::BitVector finishedBlocks(blocks.size());
159 for (
unsigned i = 0; !finishedBlocks.all(); i = (i + 1) % blocks.size()) {
160 if (finishedBlocks[i])
162 for (
unsigned k = 0; k < batchSize;) {
163 if (iters[i] == blocks[i]->
end()) {
164 finishedBlocks.set(i);
167 auto *op = builder.clone(*iters[i], mapping);
168 if (isa<InstructionOpInterface>(op))
174 materializedSequences[value] = interleavedBlock;
175 numSequencesInterleaved += blocks.size();
178LogicalResult SequenceInliner::inlineSequences(TestOp testOp) {
179 LLVM_DEBUG(llvm::dbgs() <<
"\n=== Processing test @" << testOp.getSymName()
182 SmallVector<Operation *> toDelete;
183 for (
auto &op : *testOp.getBody()) {
184 auto result = dispatchOpVisitor(&op);
188 if (*result == DeletionKind::Delete)
189 toDelete.push_back(&op);
192 for (
auto *op :
llvm::reverse(toDelete))
198void InlineSequencesPass::runOnOperation() {
199 auto moduleOp = getOperation();
200 SequenceInliner inliner(moduleOp);
203 for (
auto testOp : moduleOp.getOps<TestOp>())
204 if (failed(inliner.inlineSequences(testOp)))
205 return signalPassFailure();
209 for (
auto seqOp :
llvm::make_early_inc_range(moduleOp.getOps<SequenceOp>()))
212 numSequencesInlined = inliner.numSequencesInlined;
213 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.