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