15#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16#include "mlir/Dialect/Func/IR/FuncOps.h"
17#include "mlir/IR/Dominance.h"
18#include "mlir/Pass/Pass.h"
23#define GEN_PASS_DEF_MEMORYTOBLOCKARGUMENT
24#include "circt/Dialect/LLHD/Transforms/LLHDPasses.h.inc"
31struct MemoryToBlockArgumentPass
32 :
public circt::llhd::impl::MemoryToBlockArgumentBase<
33 MemoryToBlockArgumentPass> {
34 void runOnOperation()
override;
35 void runOnProcess(llhd::ProcessOp operation);
42 std::set<Block *> &df) {
43 mlir::DominanceInfo dom(op);
44 for (Block &block : op->getRegion(0).getBlocks()) {
45 for (Block *pred : block.getPredecessors()) {
46 if (dom.dominates(frontierOf, pred) &&
47 !dom.properlyDominates(frontierOf, &block) &&
48 block.getOps<llhd::VarOp>().
empty()) {
57static void getDFClosure(SmallVectorImpl<Block *> &initialSet, Operation *op,
58 std::set<Block *> &closure) {
60 for (Block *block : initialSet) {
65 for (Block *block : closure) {
57static void getDFClosure(SmallVectorImpl<Block *> &initialSet, Operation *op, {
…}
75 Block *successsor, Value toAppend) {
76 if (
auto wait = dyn_cast<llhd::WaitOp>(terminator)) {
77 wait.getDestOperandsMutable().append(toAppend);
78 }
else if (
auto br = dyn_cast<mlir::cf::BranchOp>(terminator)) {
79 br.getDestOperandsMutable().append(toAppend);
80 }
else if (
auto condBr = dyn_cast<mlir::cf::CondBranchOp>(terminator)) {
81 if (condBr.getFalseDest() == successsor) {
82 condBr.getFalseDestOperandsMutable().append(toAppend);
84 condBr.getTrueDestOperandsMutable().append(toAppend);
87 llvm_unreachable(
"unsupported terminator op");
91void MemoryToBlockArgumentPass::runOnOperation() {
92 for (
auto proc : getOperation().getOps<llhd::ProcessOp>())
96void MemoryToBlockArgumentPass::runOnProcess(llhd::ProcessOp operation) {
97 OpBuilder builder(operation);
101 WalkResult result = operation.getBody().walk([](Operation *op) -> WalkResult {
102 if (op->getNumRegions() > 0 &&
103 !op->hasTrait<OpTrait::IsIsolatedFromAbove>())
104 return WalkResult::interrupt();
105 return WalkResult::advance();
107 if (result.wasInterrupted())
113 SmallVector<Value, 16> vars(operation->getRegion(0).getOps<llhd::VarOp>());
117 for (
auto *var = vars.begin(); var != vars.end(); ++var) {
118 for (Operation *user : var->getUsers()) {
119 if (!isa<llhd::LoadOp>(user) && !isa<llhd::StoreOp>(user)) {
127 for (Value var : vars) {
128 SmallVector<Block *, 16> defBlocks;
130 var.getDefiningOp<llhd::VarOp>().getOperation()->getBlock());
131 operation->walk([&](llhd::StoreOp op) {
132 if (op.getPointer() == var)
133 defBlocks.push_back(op.getOperation()->getBlock());
136 std::sort(defBlocks.begin(), defBlocks.end());
137 defBlocks.erase(std::unique(defBlocks.begin(), defBlocks.end()),
141 std::set<Block *> joinPoints;
144 for (Block *jp : joinPoints) {
146 BlockArgument phi = jp->addArgument(
147 cast<llhd::PtrType>(var.getType()).getElementType(), var.getLoc());
151 for (Block *pred : jp->getPredecessors()) {
153 builder.setInsertionPoint(pred->getTerminator());
154 Value load = llhd::LoadOp::create(
155 builder, pred->getTerminator()->getLoc(),
156 cast<llhd::PtrType>(var.getType()).getElementType(), var);
162 builder.setInsertionPointToStart(jp);
163 llhd::StoreOp::create(builder, jp->front().getLoc(), var, phi);
168 DenseMap<Block *, Value> outputMap;
169 SmallPtrSet<Block *, 32> workQueue;
170 SmallPtrSet<Block *, 32> workDone;
172 workQueue.insert(&operation->getRegion(0).front());
174 while (!workQueue.empty()) {
176 Block *block = *workQueue.begin();
177 workQueue.erase(block);
180 Value currStoredValue;
184 for (Block *pred : block->getPredecessors()) {
192 if (!currStoredValue && outputMap.count(pred)) {
193 currStoredValue = outputMap[pred];
199 for (
auto op = block->begin(); op != block->end(); ++op) {
202 if (
auto store = dyn_cast<llhd::StoreOp>(op)) {
203 if (store.getPointer() == var) {
204 currStoredValue = store.getValue();
206 store.getOperation()->dropAllReferences();
212 }
else if (
auto varOp = dyn_cast<llhd::VarOp>(op)) {
213 if (varOp.getResult() == var)
214 currStoredValue = varOp.getInit();
218 }
else if (
auto load = dyn_cast<llhd::LoadOp>(op)) {
219 if (load.getPointer() == var && currStoredValue) {
221 load.getResult().replaceAllUsesWith(currStoredValue);
222 load.getOperation()->dropAllReferences();
229 outputMap.insert(std::make_pair(block, currStoredValue));
231 workDone.insert(block);
235 for (Block *succ : block->getSuccessors()) {
236 if (!workDone.count(succ))
237 workQueue.insert(succ);
244 for (Value var : vars) {
245 Operation *op = var.getDefiningOp();
246 op->dropAllDefinedValueUses();
247 op->dropAllReferences();
MlirType uint64_t numElements
static void addBlockOperandToTerminator(Operation *terminator, Block *successsor, Value toAppend)
Add a block argument to a given terminator.
static void getDominanceFrontier(Block *frontierOf, Operation *op, std::set< Block * > &df)
Add the dominance fontier blocks of 'frontierOf' to the 'df' set.
static void getDFClosure(SmallVectorImpl< Block * > &initialSet, Operation *op, std::set< Block * > &closure)
Add the blocks in the closure of the dominance fontier relation of all the block in 'initialSet' to '...
static InstancePath empty
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.