17 using namespace circt;
22 return v.getType().isa<dc::TokenType, dc::ValueType>();
26 for (
int i = 0, e = op->getNumOperands(); i < e; ++i)
27 if (op->getOperand(i) == oldVal) {
28 op->setOperand(i, newVal);
35 rewriter.setInsertionPointAfterValue(v);
36 if (v.getType().isa<ValueType>()) {
38 v = rewriter.create<UnpackOp>(v.getLoc(), v).getToken();
41 rewriter.create<SinkOp>(v.getLoc(), v);
45 static void insertFork(Value result, OpBuilder &rewriter) {
46 rewriter.setInsertionPointAfterValue(result);
48 std::vector<Operation *> opsToProcess;
49 for (
auto &u : result.getUses())
50 opsToProcess.push_back(u.getOwner());
52 bool isValue = result.getType().isa<ValueType>();
56 auto unpack = rewriter.create<UnpackOp>(result.getLoc(), result);
57 token = unpack.getToken();
58 value = unpack.getOutput();
62 auto forkSize = opsToProcess.size();
63 auto newFork = rewriter.create<ForkOp>(token.getLoc(), token, forkSize);
68 for (
auto [op, forkOutput] : llvm::zip(opsToProcess, newFork->getResults())) {
69 Value forkRes = forkOutput;
72 rewriter.create<PackOp>(forkRes.getLoc(), forkRes,
value).getOutput();
79 static LogicalResult
addForkOps(Block &block, OpBuilder &rewriter) {
82 llvm::SmallVector<Operation *> opsToProcess;
83 for (
auto &op : block.getOperations())
84 opsToProcess.push_back(&op);
86 for (Operation *op : opsToProcess) {
88 if (!op->hasTrait<OpTrait::IsTerminator>()) {
89 for (
auto result : op->getResults()) {
94 if (!result.use_empty() && !result.hasOneUse())
100 for (
auto barg : block.getArguments())
101 if (!barg.use_empty() && !barg.hasOneUse())
108 static LogicalResult
addSinkOps(Block &block, OpBuilder &rewriter) {
109 for (
auto arg : block.getArguments()) {
116 llvm::SmallVector<Operation *> opsToProcess;
117 for (
auto &op : block.getOperations())
118 opsToProcess.push_back(&op);
120 for (Operation *op : opsToProcess) {
121 if (op->getNumResults() == 0)
124 for (
auto result : op->getResults()) {
125 if (
isDCTyped(result) && result.use_empty())
134 struct DCMaterializeForksSinksPass
135 :
public DCMaterializeForksSinksBase<DCMaterializeForksSinksPass> {
136 void runOnOperation()
override {
137 auto funcOp = getOperation();
138 if (funcOp.isExternal())
142 auto walkRes = funcOp.walk([&](mlir::Block *block) {
145 return WalkResult::interrupt();
147 return WalkResult::advance();
150 if (walkRes.wasInterrupted())
151 return signalPassFailure();
155 struct DCDematerializeForksSinksPass
156 :
public DCDematerializeForksSinksBase<DCDematerializeForksSinksPass> {
157 void runOnOperation()
override {
158 auto funcOp = getOperation();
160 if (funcOp.isExternal())
162 funcOp.walk([&](dc::SinkOp sinkOp) { sinkOp.erase(); });
163 funcOp.walk([&](dc::ForkOp forkOp) {
164 for (
auto res : forkOp->getResults())
165 res.replaceAllUsesWith(forkOp.getOperand());
174 return std::make_unique<DCMaterializeForksSinksPass>();
178 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()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...