CIRCT  19.0.0git
IbisArgifyBlocksPass.cpp
Go to the documentation of this file.
1 //===- IbisArgifyBlocksPass.cpp -------------------------------------------===//
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 
11 #include "mlir/Pass/Pass.h"
12 
17 
18 #include "mlir/Transforms/DialectConversion.h"
19 
20 namespace circt {
21 namespace ibis {
22 #define GEN_PASS_DEF_IBISARGIFYBLOCKS
23 #include "circt/Dialect/Ibis/IbisPasses.h.inc"
24 } // namespace ibis
25 } // namespace circt
26 
27 using namespace circt;
28 using namespace ibis;
29 
30 namespace {
31 
32 // A mapping between values and op operands who use them. A MapVector is used to
33 // ensure determinism.
34 using ValueMapping = llvm::MapVector<Value, llvm::SmallVector<OpOperand *>>;
35 
36 // Returns a map of values to op operands, of values that are defined
37 // outside of the block op.
38 static void getExternallyDefinedOperands(StaticBlockOp blockOp,
39  ValueMapping &mapping) {
40  Block *blockBodyBlock = blockOp.getBodyBlock();
41  for (Operation &op : *blockBodyBlock) {
42  for (OpOperand &operand : op.getOpOperands()) {
43  Value v = operand.get();
44  if (v.getParentBlock() != blockBodyBlock)
45  mapping[v].push_back(&operand);
46  }
47  }
48 }
49 
50 struct BlockConversionPattern : public OpConversionPattern<StaticBlockOp> {
52 
53  LogicalResult
54  matchAndRewrite(StaticBlockOp blockOp, OpAdaptor adaptor,
55  ConversionPatternRewriter &rewriter) const override {
56  ValueMapping mapping;
57  getExternallyDefinedOperands(blockOp, mapping);
58  Block *bodyBlock = blockOp.getBodyBlock();
59 
60  auto isolatedBlock = rewriter.create<IsolatedStaticBlockOp>(
61  blockOp.getLoc(), blockOp.getResultTypes(), blockOp.getOperands(),
62  blockOp.getMaxThreadsAttr());
63  // Erase the default terminator.
64  Block *isolatedBlockBody = isolatedBlock.getBodyBlock();
65  rewriter.eraseOp(isolatedBlockBody->getTerminator());
66  llvm::SmallVector<Value> preAddBArgs;
67  llvm::copy(blockOp.getBodyBlock()->getArguments(),
68  std::back_inserter(preAddBArgs));
69 
70  // Add inputs and block arguments to the block, and replace the operand
71  // uses.
72  for (auto &[value, uses] : mapping) {
73  isolatedBlock.getInputsMutable().append({value});
74  auto newArg =
75  isolatedBlockBody->addArgument(value.getType(), value.getLoc());
76  for (OpOperand *operand : uses)
77  operand->set(newArg);
78  }
79  // Inline the old block into the isolated block
80  rewriter.mergeBlocks(bodyBlock, isolatedBlockBody, preAddBArgs);
81  rewriter.replaceOp(blockOp, isolatedBlock.getResults());
82  return success();
83  }
84 };
85 
86 struct ArgifyBlocksPass
87  : public circt::ibis::impl::IbisArgifyBlocksBase<ArgifyBlocksPass> {
88  void runOnOperation() override;
89 };
90 } // anonymous namespace
91 
92 void ArgifyBlocksPass::runOnOperation() {
93  auto *ctx = &getContext();
94  ConversionTarget target(*ctx);
95  target.addIllegalOp<StaticBlockOp>();
96  target.addLegalDialect<IbisDialect>();
97 
98  RewritePatternSet patterns(ctx);
99  patterns.add<BlockConversionPattern>(ctx);
100 
101  if (failed(
102  applyPartialConversion(getOperation(), target, std::move(patterns))))
103  signalPassFailure();
104 }
105 
106 std::unique_ptr<Pass> circt::ibis::createArgifyBlocksPass() {
107  return std::make_unique<ArgifyBlocksPass>();
108 }
std::unique_ptr< mlir::Pass > createArgifyBlocksPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21