15 #include "mlir/Pass/Pass.h"
19 #define GEN_PASS_DEF_DCMATERIALIZEFORKSSINKS
20 #define GEN_PASS_DEF_DCDEMATERIALIZEFORKSSINKS
21 #include "circt/Dialect/DC/DCPasses.h.inc"
25 using namespace circt;
30 return isa<dc::TokenType, dc::ValueType>(v.getType());
34 for (
int i = 0, e = op->getNumOperands(); i < e; ++i)
35 if (op->getOperand(i) == oldVal) {
36 op->setOperand(i, newVal);
43 rewriter.setInsertionPointAfterValue(v);
44 if (isa<ValueType>(v.getType())) {
46 v = rewriter.create<UnpackOp>(v.getLoc(), v).getToken();
49 rewriter.create<SinkOp>(v.getLoc(), v);
53 static void insertFork(Value result, OpBuilder &rewriter) {
54 rewriter.setInsertionPointAfterValue(result);
56 std::vector<Operation *> opsToProcess;
57 for (
auto &u : result.getUses())
58 opsToProcess.push_back(u.getOwner());
60 bool isValue = isa<ValueType>(result.getType());
64 auto unpack = rewriter.create<UnpackOp>(result.getLoc(), result);
65 token = unpack.getToken();
66 value = unpack.getOutput();
70 auto forkSize = opsToProcess.size();
71 auto newFork = rewriter.create<ForkOp>(token.getLoc(), token, forkSize);
76 for (
auto [op, forkOutput] : llvm::zip(opsToProcess, newFork->getResults())) {
77 Value forkRes = forkOutput;
80 rewriter.create<PackOp>(forkRes.getLoc(), forkRes, value).getOutput();
87 static LogicalResult
addForkOps(Block &block, OpBuilder &rewriter) {
90 llvm::SmallVector<Operation *> opsToProcess;
91 for (
auto &op : block.getOperations())
92 opsToProcess.push_back(&op);
94 for (Operation *op : opsToProcess) {
96 if (!op->hasTrait<OpTrait::IsTerminator>()) {
97 for (
auto result : op->getResults()) {
102 if (!result.use_empty() && !result.hasOneUse())
108 for (
auto barg : block.getArguments())
109 if (!barg.use_empty() && !barg.hasOneUse())
116 static LogicalResult
addSinkOps(Block &block, OpBuilder &rewriter) {
117 for (
auto arg : block.getArguments()) {
124 llvm::SmallVector<Operation *> opsToProcess;
125 for (
auto &op : block.getOperations())
126 opsToProcess.push_back(&op);
128 for (Operation *op : opsToProcess) {
129 if (op->getNumResults() == 0)
132 for (
auto result : op->getResults()) {
133 if (
isDCTyped(result) && result.use_empty())
142 struct DCMaterializeForksSinksPass
143 :
public circt::dc::impl::DCMaterializeForksSinksBase<
144 DCMaterializeForksSinksPass> {
145 void runOnOperation()
override {
146 auto *op = getOperation();
147 OpBuilder builder(op);
149 auto walkRes = op->walk([&](mlir::Block *block) {
152 return WalkResult::interrupt();
154 return WalkResult::advance();
157 if (walkRes.wasInterrupted())
158 return signalPassFailure();
162 struct DCDematerializeForksSinksPass
163 :
public circt::dc::impl::DCDematerializeForksSinksBase<
164 DCDematerializeForksSinksPass> {
165 void runOnOperation()
override {
166 auto *op = getOperation();
167 op->walk([&](dc::SinkOp sinkOp) { sinkOp.erase(); });
168 op->walk([&](dc::ForkOp forkOp) {
169 for (
auto res : forkOp->getResults())
170 res.replaceAllUsesWith(forkOp.getOperand());
179 return std::make_unique<DCMaterializeForksSinksPass>();
183 return std::make_unique<DCDematerializeForksSinksPass>();
static LogicalResult addSinkOps(Block &block, OpBuilder &rewriter)
static void insertSink(Value v, OpBuilder &rewriter)
static void insertFork(Value result, OpBuilder &rewriter)
static bool isDCTyped(Value v)
static LogicalResult addForkOps(Block &block, OpBuilder &rewriter)
static void replaceFirstUse(Operation *op, Value oldVal, Value newVal)
std::unique_ptr< mlir::Pass > createDCDematerializeForksSinksPass()
std::unique_ptr< mlir::Pass > createDCMaterializeForksSinksPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.