15 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16 #include "mlir/Dialect/Func/IR/FuncOps.h"
17 #include "mlir/IR/Dominance.h"
20 using namespace circt;
24 struct MemoryToBlockArgumentPass
25 :
public llhd::MemoryToBlockArgumentBase<MemoryToBlockArgumentPass> {
26 void runOnOperation()
override;
33 std::set<Block *> &df) {
34 mlir::DominanceInfo dom(op);
35 for (Block &block : op->getRegion(0).getBlocks()) {
36 for (Block *pred : block.getPredecessors()) {
37 if (dom.dominates(frontierOf, pred) &&
38 !dom.properlyDominates(frontierOf, &block) &&
39 block.getOps<llhd::VarOp>().empty()) {
48 static void getDFClosure(SmallVectorImpl<Block *> &initialSet, Operation *op,
49 std::set<Block *> &closure) {
51 for (Block *block : initialSet) {
56 for (Block *block : closure) {
66 Block *successsor, Value toAppend) {
67 if (
auto wait = dyn_cast<llhd::WaitOp>(terminator)) {
68 wait.getDestOpsMutable().append(toAppend);
69 }
else if (
auto br = dyn_cast<mlir::cf::BranchOp>(terminator)) {
70 br.getDestOperandsMutable().append(toAppend);
71 }
else if (
auto condBr = dyn_cast<mlir::cf::CondBranchOp>(terminator)) {
72 if (condBr.getFalseDest() == successsor) {
73 condBr.getFalseDestOperandsMutable().append(toAppend);
75 condBr.getTrueDestOperandsMutable().append(toAppend);
78 llvm_unreachable(
"unsupported terminator op");
82 void MemoryToBlockArgumentPass::runOnOperation() {
83 Operation *operation = getOperation();
88 WalkResult result = operation->walk([](Operation *op) -> WalkResult {
89 if (op->getNumRegions() > 0 &&
90 !op->hasTrait<OpTrait::IsIsolatedFromAbove>())
91 return WalkResult::interrupt();
92 return WalkResult::advance();
94 if (result.wasInterrupted())
100 SmallVector<Value, 16> vars;
101 for (llhd::VarOp var : operation->getRegion(0).getOps<llhd::VarOp>()) {
102 vars.push_back(var.getResult());
107 for (
auto var = vars.begin(); var != vars.end(); ++var) {
108 for (Operation *user : var->getUsers()) {
109 if (!isa<llhd::LoadOp>(user) && !isa<llhd::StoreOp>(user)) {
117 for (Value var : vars) {
118 SmallVector<Block *, 16> defBlocks;
120 var.getDefiningOp<llhd::VarOp>().getOperation()->getBlock());
121 operation->walk([&](llhd::StoreOp op) {
122 if (op.getPointer() == var)
123 defBlocks.push_back(op.getOperation()->getBlock());
126 std::sort(defBlocks.begin(), defBlocks.end());
127 defBlocks.erase(std::unique(defBlocks.begin(), defBlocks.end()),
131 std::set<Block *> joinPoints;
134 for (Block *jp : joinPoints) {
136 BlockArgument phi = jp->addArgument(
137 var.getType().cast<llhd::PtrType>().getUnderlyingType(),
142 for (Block *pred : jp->getPredecessors()) {
144 builder.setInsertionPoint(pred->getTerminator());
145 Value load =
builder.create<llhd::LoadOp>(
146 pred->getTerminator()->getLoc(),
147 var.getType().cast<llhd::PtrType>().getUnderlyingType(), var);
153 builder.setInsertionPointToStart(jp);
154 builder.create<llhd::StoreOp>(jp->front().getLoc(), var, phi);
159 DenseMap<Block *, Value> outputMap;
160 SmallPtrSet<Block *, 32> workQueue;
161 SmallPtrSet<Block *, 32> workDone;
163 workQueue.insert(&operation->getRegion(0).front());
165 while (!workQueue.empty()) {
167 Block *block = *workQueue.begin();
168 workQueue.erase(block);
171 Value currStoredValue;
175 for (Block *pred : block->getPredecessors()) {
183 if (!currStoredValue && outputMap.count(pred)) {
184 currStoredValue = outputMap[pred];
190 for (
auto op = block->begin(); op != block->end(); ++op) {
193 if (
auto store = dyn_cast<llhd::StoreOp>(op)) {
194 if (store.getPointer() == var) {
195 currStoredValue = store.getValue();
197 store.getOperation()->dropAllReferences();
203 }
else if (
auto varOp = dyn_cast<llhd::VarOp>(op)) {
204 if (varOp.getResult() == var)
205 currStoredValue = varOp.getInit();
209 }
else if (
auto load = dyn_cast<llhd::LoadOp>(op)) {
210 if (load.getPointer() == var && currStoredValue) {
212 load.getResult().replaceAllUsesWith(currStoredValue);
213 load.getOperation()->dropAllReferences();
220 outputMap.insert(std::make_pair(block, currStoredValue));
222 workDone.insert(block);
226 for (Block *succ : block->getSuccessors()) {
227 if (!workDone.count(succ))
228 workQueue.insert(succ);
235 for (Value var : vars) {
236 Operation *op = var.getDefiningOp();
237 op->dropAllDefinedValueUses();
238 op->dropAllReferences();
243 std::unique_ptr<OperationPass<llhd::ProcOp>>
245 return std::make_unique<MemoryToBlockArgumentPass>();
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 '...
std::unique_ptr< OperationPass< ProcOp > > createMemoryToBlockArgumentPass()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...