17 #include "mlir/Dialect/Affine/IR/AffineOps.h"
18 #include "mlir/Dialect/Arith/IR/Arith.h"
19 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
20 #include "mlir/Dialect/Func/IR/FuncOps.h"
21 #include "mlir/Dialect/MemRef/IR/MemRef.h"
22 #include "mlir/IR/BuiltinTypes.h"
23 #include "mlir/IR/OperationSupport.h"
24 #include "mlir/IR/PatternMatch.h"
25 #include "mlir/Support/IndentedOstream.h"
26 #include "llvm/ADT/TypeSwitch.h"
28 using namespace circt;
29 using namespace handshake;
36 for (
int i = 0, e = op->getNumOperands(); i < e; ++i)
37 if (op->getOperand(i) == oldVal) {
38 op->setOperand(i, newVal);
45 rewriter.setInsertionPointAfterValue(val);
46 rewriter.create<SinkOp>(val.getLoc(), val);
52 void insertFork(Value result,
bool isLazy, OpBuilder &rewriter) {
54 std::vector<Operation *> opsToProcess;
55 for (
auto &u : result.getUses())
56 opsToProcess.push_back(u.getOwner());
59 rewriter.setInsertionPointAfterValue(result);
60 auto forkSize = opsToProcess.size();
63 newOp = rewriter.create<LazyForkOp>(result.getLoc(), result, forkSize);
65 newOp = rewriter.create<ForkOp>(result.getLoc(), result, forkSize);
70 for (
int i = 0, e = forkSize; i < e; ++i)
76 LogicalResult
addForkOps(Region &r, OpBuilder &rewriter) {
77 for (Operation &op : r.getOps()) {
79 if (op.getNumSuccessors() == 0 && !isa<ForkOp>(op)) {
80 for (
auto result : op.getResults()) {
82 if (!result.use_empty() && !result.hasOneUse())
88 for (
auto barg : r.front().getArguments())
89 if (!barg.use_empty() && !barg.hasOneUse())
96 LogicalResult
addSinkOps(Region &r, OpBuilder &rewriter) {
99 for (Block &block : r) {
100 for (
auto arg : block.getArguments()) {
104 for (Operation &op : block) {
109 if (isa<mlir::cf::CondBranchOp, mlir::cf::BranchOp, memref::LoadOp,
110 AffineReadOpInterface, AffineForOp>(op))
113 if (op.getNumResults() == 0)
116 for (
auto result : op.getResults())
117 if (result.use_empty())
128 struct HandshakeMaterializeForksSinksPass
129 :
public HandshakeMaterializeForksSinksBase<
130 HandshakeMaterializeForksSinksPass> {
131 void runOnOperation()
override {
132 handshake::FuncOp op = getOperation();
139 return signalPassFailure();
143 struct HandshakeDematerializeForksSinksPass
144 :
public HandshakeDematerializeForksSinksBase<
145 HandshakeDematerializeForksSinksPass> {
146 void runOnOperation()
override {
147 handshake::FuncOp op = getOperation();
151 llvm::make_early_inc_range(op.getOps<handshake::SinkOp>()))
155 llvm::make_early_inc_range(op.getOps<handshake::ForkOp>())) {
156 for (
auto res : forkOp->getResults())
157 res.replaceAllUsesWith(forkOp.getOperand());
165 std::unique_ptr<mlir::Pass>
167 return std::make_unique<HandshakeMaterializeForksSinksPass>();
170 std::unique_ptr<mlir::Pass>
172 return std::make_unique<HandshakeDematerializeForksSinksPass>();
static void insertSink(Value val, OpBuilder &rewriter)
static void replaceFirstUse(Operation *op, Value oldVal, Value newVal)
DenseMap< Block *, std::vector< Value > > BlockValues
std::unique_ptr< mlir::Pass > createHandshakeMaterializeForksSinksPass()
LogicalResult addForkOps(Region &r, OpBuilder &rewriter)
LogicalResult verifyAllValuesHasOneUse(handshake::FuncOp op)
std::unique_ptr< mlir::Pass > createHandshakeDematerializeForksSinksPass()
void insertFork(Value result, bool isLazy, OpBuilder &rewriter)
LogicalResult addSinkOps(Region &r, OpBuilder &rewriter)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.