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