CIRCT 23.0.0git
Loading...
Searching...
No Matches
SimpleTestInlinerPass.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
12#include "mlir/IR/PatternMatch.h"
13
14namespace circt {
15namespace rtg {
16#define GEN_PASS_DEF_SIMPLETESTINLINERPASS
17#include "circt/Dialect/RTG/Transforms/RTGPasses.h.inc"
18} // namespace rtg
19} // namespace circt
20
21using namespace mlir;
22using namespace circt;
23using namespace circt::rtg;
24
25//===----------------------------------------------------------------------===//
26// Simple Test Inliner Pass
27//===----------------------------------------------------------------------===//
28
29namespace {
30struct SimpleTestInlinerPass
31 : public rtg::impl::SimpleTestInlinerPassBase<SimpleTestInlinerPass> {
32 using Base::Base;
33 void runOnOperation() override;
34};
35} // namespace
36
37void SimpleTestInlinerPass::runOnOperation() {
38 const auto &symTbl = getAnalysis<SymbolTable>();
39 IRRewriter rewriter(getOperation());
40
41 for (auto fileOp : getOperation().getOps<emit::FileOp>()) {
42 rewriter.setInsertionPointToStart(fileOp.getBody());
43 auto segOp =
44 SegmentOp::create(rewriter, fileOp->getLoc(), SegmentKind::Text);
45 segOp.getBodyRegion().emplaceBlock();
46
47 Block *fileBlock = fileOp.getBody();
48 Block *segBlock = segOp.getBody();
49
50 auto opsToMove = llvm::make_early_inc_range(
51 llvm::make_range(std::next(fileBlock->begin()), fileBlock->end()));
52 for (auto &op : opsToMove)
53 op.moveBefore(segBlock, segBlock->end());
54
55 for (auto refOp : llvm::make_early_inc_range(segOp.getOps<emit::RefOp>())) {
56 auto testOp = symTbl.lookup<TestOp>(refOp.getTargetAttr().getAttr());
57 if (!testOp) {
58 refOp.emitError("invalid symbol reference: ") << refOp.getTargetAttr();
59 return signalPassFailure();
60 }
61
62 bool allArgsUnused =
63 llvm::all_of(testOp.getBody()->getArguments(),
64 [](auto arg) { return arg.use_empty(); });
65 if (!allArgsUnused) {
66 testOp->emitError("cannot inline test with used arguments");
67 return signalPassFailure();
68 }
69
70 testOp.getBody()->eraseArguments(0, testOp.getBody()->getNumArguments());
71 rewriter.setInsertionPoint(refOp);
72 auto testBeginComment = ConstantOp::create(
73 rewriter, refOp->getLoc(),
74 StringAttr::get(Twine("Begin of test '") + testOp.getSymName() + "'",
75 StringType::get(rewriter.getContext())));
76 CommentOp::create(rewriter, refOp->getLoc(), testBeginComment);
77 auto newTestOp = cast<TestOp>(testOp->clone());
78 rewriter.inlineBlockBefore(newTestOp.getBody(), refOp, {});
79 auto testEndComment = ConstantOp::create(
80 rewriter, refOp->getLoc(),
81 StringAttr::get(Twine("End of test '") + testOp.getSymName() + "'",
82 StringType::get(rewriter.getContext())));
83 CommentOp::create(rewriter, refOp->getLoc(), testEndComment);
84 newTestOp.erase();
85 refOp.erase();
86 }
87 }
88
89 for (auto &op : llvm::make_early_inc_range(getOperation().getOps()))
90 if (isa<TargetOp, TestOp>(&op))
91 op.erase();
92}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition emit.py:1
Definition rtg.py:1