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())
117 static LogicalResult
addSinkOps(Block &block, OpBuilder &rewriter) {
118 for (
auto arg : block.getArguments()) {
125 llvm::SmallVector<Operation *> opsToProcess;
126 for (
auto &op : block.getOperations())
127 opsToProcess.push_back(&op);
129 for (Operation *op : opsToProcess) {
130 if (op->getNumResults() == 0)
133 for (
auto result : op->getResults()) {
134 if (
isDCTyped(result) && result.use_empty())
143 struct DCMaterializeForksSinksPass
144 :
public circt::dc::impl::DCMaterializeForksSinksBase<
145 DCMaterializeForksSinksPass> {
146 void runOnOperation()
override {
147 auto *op = getOperation();
148 OpBuilder builder(op);
150 auto walkRes = op->walk([&](mlir::Block *block) {
153 return WalkResult::interrupt();
155 return WalkResult::advance();
158 if (walkRes.wasInterrupted())
159 return signalPassFailure();
163 struct DCDematerializeForksSinksPass
164 :
public circt::dc::impl::DCDematerializeForksSinksBase<
165 DCDematerializeForksSinksPass> {
166 void runOnOperation()
override {
167 auto *op = getOperation();
168 op->walk([&](dc::SinkOp sinkOp) { sinkOp.erase(); });
169 op->walk([&](dc::ForkOp forkOp) {
170 for (
auto res : forkOp->getResults())
171 res.replaceAllUsesWith(forkOp.getOperand());
180 return std::make_unique<DCMaterializeForksSinksPass>();
184 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.