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