CIRCT  19.0.0git
IbisInlineSBlocksPass.cpp
Go to the documentation of this file.
1 //===- IbisInlineSBlocksPass.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 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
18 
19 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
20 
22 #include "mlir/Transforms/DialectConversion.h"
23 
24 #include <iterator>
25 
26 namespace circt {
27 namespace ibis {
28 #define GEN_PASS_DEF_IBISINLINESBLOCKS
29 #include "circt/Dialect/Ibis/IbisPasses.h.inc"
30 } // namespace ibis
31 } // namespace circt
32 
33 using namespace mlir;
34 using namespace circt;
35 using namespace ibis;
36 
37 namespace {
38 
39 struct InlineSBlocksPass
40  : public circt::ibis::impl::IbisInlineSBlocksBase<InlineSBlocksPass> {
41  void runOnOperation() override;
42 };
43 
44 class InlineSBlocksPattern : public OpConversionPattern<ibis::StaticBlockOp> {
45 public:
47  using OpAdaptor =
49 
50  LogicalResult
51  matchAndRewrite(ibis::StaticBlockOp op, OpAdaptor adaptor,
52  ConversionPatternRewriter &rewriter) const override {
53  Location loc = op.getLoc();
54 
55  // We only create block markers in case the sblock has attributes.
56  bool hasAttributes = !op->getAttrs().empty();
57 
58  if (hasAttributes) {
59  // Start the inline block...
60  auto inlineStart = rewriter.create<ibis::InlineStaticBlockBeginOp>(loc);
61  inlineStart->setAttrs(op->getAttrs());
62  }
63 
64  // Inline the sblock.
65  Block *sblockBody = op.getBodyBlock();
66  BlockReturnOp ret = cast<BlockReturnOp>(sblockBody->getTerminator());
67  rewriter.inlineBlockBefore(sblockBody, op->getNextNode());
68 
69  // Replace the ibis.sblock return values with the values that were defined
70  // (returned from) within the sblock body, and erase the return op.
71  for (auto [res, val] : llvm::zip(op.getResults(), ret.getRetValues()))
72  rewriter.replaceAllUsesWith(res, val);
73 
74  if (hasAttributes) {
75  // Close the inline block
76  rewriter.setInsertionPoint(ret);
77  rewriter.create<ibis::InlineStaticBlockEndOp>(loc);
78  }
79 
80  rewriter.eraseOp(ret);
81  rewriter.eraseOp(op);
82  return success();
83  }
84 };
85 
86 } // anonymous namespace
87 
88 void InlineSBlocksPass::runOnOperation() {
89  MethodOp parent = getOperation();
90  ConversionTarget target(getContext());
91  target.addIllegalOp<ibis::StaticBlockOp>();
92  // Mark everything but `ibis.sblock` as legal - we need a legalization pattern
93  // for any possible op that gets inlined from a block.
94  target.markUnknownOpDynamicallyLegal([](Operation *op) { return true; });
95  RewritePatternSet patterns(&getContext());
96  patterns.add<InlineSBlocksPattern>(&getContext());
97 
98  if (failed(applyPartialConversion(parent, target, std::move(patterns))))
99  return signalPassFailure();
100 }
101 
102 std::unique_ptr<Pass> circt::ibis::createInlineSBlocksPass() {
103  return std::make_unique<InlineSBlocksPass>();
104 }
std::unique_ptr< mlir::Pass > createInlineSBlocksPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21