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/Pass/Pass.h"
26 #include "mlir/Support/IndentedOstream.h"
27 #include "llvm/ADT/TypeSwitch.h"
31 #define GEN_PASS_DEF_HANDSHAKEMATERIALIZEFORKSSINKS
32 #define GEN_PASS_DEF_HANDSHAKEDEMATERIALIZEFORKSSINKS
33 #include "circt/Dialect/Handshake/HandshakePasses.h.inc"
37 using namespace circt;
38 using namespace handshake;
45 rewriter.setInsertionPointAfterValue(val);
46 rewriter.create<SinkOp>(val.getLoc(), val);
51 static LogicalResult
addForkOps(Region &r, OpBuilder &rewriter) {
52 for (Operation &op : r.getOps()) {
54 if (op.getNumSuccessors() == 0 && !isa<ForkOp>(op)) {
55 for (
auto result : op.getResults()) {
57 if (!result.use_empty() && !result.hasOneUse())
63 for (
auto barg : r.front().getArguments())
64 if (!barg.use_empty() && !barg.hasOneUse())
71 static LogicalResult
addSinkOps(Region &r, OpBuilder &rewriter) {
74 for (Block &block : r) {
75 for (
auto arg : block.getArguments()) {
79 for (Operation &op : block) {
84 if (isa<mlir::cf::CondBranchOp, mlir::cf::BranchOp, memref::LoadOp,
85 AffineReadOpInterface, AffineForOp>(op))
88 if (op.getNumResults() == 0)
91 for (
auto result : op.getResults())
92 if (result.use_empty())
100 struct HandshakeMaterializeForksSinksPass
101 :
public circt::handshake::impl::HandshakeMaterializeForksSinksBase<
102 HandshakeMaterializeForksSinksPass> {
103 void runOnOperation()
override {
104 handshake::FuncOp op = getOperation();
107 OpBuilder builder(op);
108 if (
addForkOps(op.getRegion(), builder).failed() ||
109 addSinkOps(op.getRegion(), builder).failed() ||
111 return signalPassFailure();
115 struct HandshakeDematerializeForksSinksPass
116 :
public circt::handshake::impl::HandshakeDematerializeForksSinksBase<
117 HandshakeDematerializeForksSinksPass> {
118 void runOnOperation()
override {
119 handshake::FuncOp op = getOperation();
123 llvm::make_early_inc_range(op.getOps<handshake::SinkOp>()))
127 llvm::make_early_inc_range(op.getOps<handshake::ForkOp>())) {
128 for (
auto res : forkOp->getResults())
129 res.replaceAllUsesWith(forkOp.getOperand());
137 std::unique_ptr<mlir::Pass>
139 return std::make_unique<HandshakeMaterializeForksSinksPass>();
142 std::unique_ptr<mlir::Pass>
144 return std::make_unique<HandshakeDematerializeForksSinksPass>();
static void insertSink(Value val, OpBuilder &rewriter)
static LogicalResult addSinkOps(Region &r, OpBuilder &rewriter)
Adds sink operations to any unused value in r.
static LogicalResult addForkOps(Region &r, OpBuilder &rewriter)
Insert Fork Operation for every operation and function argument with more than one successor.
DenseMap< Block *, std::vector< Value > > BlockValues
std::unique_ptr< mlir::Pass > createHandshakeMaterializeForksSinksPass()
LogicalResult verifyAllValuesHasOneUse(handshake::FuncOp op)
Checks all block arguments and values within op to ensure that all values have exactly one use.
std::unique_ptr< mlir::Pass > createHandshakeDematerializeForksSinksPass()
void insertFork(Value result, bool isLazy, OpBuilder &rewriter)
Adds fork operations to any value with multiple uses in r.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.