CIRCT 20.0.0git
Loading...
Searching...
No Matches
EarlyCodeMotionPass.cpp
Go to the documentation of this file.
1//===- EarlyCodeMotionPass.cpp - Implement Early Code Motion Pass ---------===//
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// Implement pass to move allowed instructions as far up in the CFG as possible.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TemporalRegions.h"
16#include "circt/Support/LLVM.h"
17#include "mlir/IR/Dominance.h"
18#include "mlir/Pass/Pass.h"
19
20namespace circt {
21namespace llhd {
22#define GEN_PASS_DEF_EARLYCODEMOTION
23#include "circt/Dialect/LLHD/Transforms/Passes.h.inc"
24} // namespace llhd
25} // namespace circt
26
27using namespace circt;
28namespace {
29struct EarlyCodeMotionPass
30 : public circt::llhd::impl::EarlyCodeMotionBase<EarlyCodeMotionPass> {
31 void runOnOperation() override;
32 void runOnProcess(llhd::ProcessOp proc);
33};
34} // namespace
35
36/// Calculate intersection of two vectors, returns a new vector
37static SmallVector<Block *, 8> intersection(SmallVectorImpl<Block *> &v1,
38 SmallVectorImpl<Block *> &v2) {
39 SmallVector<Block *, 8> res;
40 std::sort(v1.begin(), v1.end());
41 std::sort(v2.begin(), v2.end());
42
43 std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(),
44 std::back_inserter(res));
45 return res;
46}
47
48void EarlyCodeMotionPass::runOnOperation() {
49 for (auto proc : getOperation().getOps<llhd::ProcessOp>())
50 runOnProcess(proc);
51}
52
53void EarlyCodeMotionPass::runOnProcess(llhd::ProcessOp proc) {
55 mlir::DominanceInfo dom(proc);
56
57 DenseMap<Block *, unsigned> entryDistance;
58 SmallPtrSet<Block *, 32> workDone;
59 SmallPtrSet<Block *, 32> workPending;
60
61 Block &entryBlock = proc.getBody().front();
62 workPending.insert(&entryBlock);
63 entryDistance.insert(std::make_pair(&entryBlock, 0));
64
65 while (!workPending.empty()) {
66 Block *block = *workPending.begin();
67 workPending.erase(block);
68 workDone.insert(block);
69
70 for (auto iter = block->getOperations().begin();
71 iter != block->getOperations().end(); ++iter) {
72 Operation &op = *iter;
73 if (!isa<llhd::PrbOp>(op) && !isa<llhd::SignalOp>(op) &&
74 (!mlir::isMemoryEffectFree(&op) ||
75 op.hasTrait<OpTrait::IsTerminator>()))
76 continue;
77
78 SmallVector<Block *, 8> validPlacements;
79 // Initialize validPlacements to all blocks in the process
80 for (Block &b : proc.getBody().getBlocks())
81 validPlacements.push_back(&b);
82
83 // Delete all blocks in validPlacements that are not common to all
84 // operands
85 for (Value operand : op.getOperands()) {
86 SmallVector<Block *, 8> dominationSet;
87 Block *instBlock = nullptr;
88 if (BlockArgument arg = dyn_cast<BlockArgument>(operand)) {
89 instBlock = arg.getParentBlock();
90 } else {
91 instBlock = operand.getDefiningOp()->getBlock();
92 }
93
94 for (Block &b : proc.getBody().getBlocks()) {
95 if (dom.dominates(instBlock, &b))
96 dominationSet.push_back(&b);
97 }
98 validPlacements = intersection(dominationSet, validPlacements);
99 }
100
101 // The probe instruction has to stay in the same temporal region
102 if (isa<llhd::PrbOp>(op)) {
103 SmallVector<Block *, 8> blocksInTR =
104 trAnalysis.getBlocksInTR(trAnalysis.getBlockTR(block));
105 validPlacements = intersection(validPlacements, blocksInTR);
106 }
107
108 if (validPlacements.empty())
109 continue;
110
111 // Move the instruction to the block which is the closest to the entry
112 // block (and valid)
113 unsigned minBBdist = -1;
114 Block *minBB = nullptr;
115 for (Block *b : validPlacements) {
116 if (!entryDistance.count(b))
117 continue;
118 if (entryDistance[b] < minBBdist) {
119 minBBdist = entryDistance[b];
120 minBB = b;
121 }
122 }
123
124 if (!minBB || minBB == op.getBlock())
125 continue;
126
127 auto prev = std::prev(iter);
128 op.moveBefore(minBB->getTerminator());
129 iter = prev;
130 }
131
132 // Add successors of this block
133 for (Block *succ : block->getSuccessors()) {
134 if (!workDone.count(succ)) {
135 workPending.insert(succ);
136 assert(entryDistance.count(block) &&
137 "ECM: block has to be present in entryDistance map");
138 unsigned nextDist = entryDistance[block] + 1;
139 entryDistance.insert(std::make_pair(succ, nextDist));
140 }
141 }
142 }
143}
144
145std::unique_ptr<OperationPass<hw::HWModuleOp>>
147 return std::make_unique<EarlyCodeMotionPass>();
148}
assert(baseType &&"element must be base type")
static SmallVector< Block *, 8 > intersection(SmallVectorImpl< Block * > &v1, SmallVectorImpl< Block * > &v2)
Calculate intersection of two vectors, returns a new vector.
std::unique_ptr< OperationPass< hw::HWModuleOp > > createEarlyCodeMotionPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
SmallVector< Block *, 8 > getBlocksInTR(int) const