15 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16 #include "mlir/IR/PatternMatch.h"
17 #include "mlir/IR/Visitors.h"
18 #include "mlir/Pass/Pass.h"
19 #include "llvm/Support/Debug.h"
21 #define DEBUG_TYPE "llhd-process-lowering"
25 #define GEN_PASS_DEF_PROCESSLOWERING
26 #include "circt/Dialect/LLHD/Transforms/Passes.h.inc"
31 using namespace circt;
35 struct ProcessLoweringPass
36 :
public circt::llhd::impl::ProcessLoweringBase<ProcessLoweringPass> {
37 void runOnOperation()
override;
40 static LogicalResult isProcValidToLower(llhd::ProcessOp op) {
41 if (op.getBody().getBlocks().size() != 2) {
43 llvm::dbgs() <<
"process-lowering only supports processes with "
44 "two basic blocks where the first "
45 "contains a 'cf.br' terminator and the second one is "
46 "terminated by a 'llhd.wait' operation\n";
51 Block &first = op.getBody().front();
52 Block &last = op.getBody().back();
54 if (!last.getArguments().empty()) {
56 llvm::dbgs() <<
"the second block (containing the "
57 "llhd.wait) is not allowed to have arguments\n";
62 if (!isa<cf::BranchOp>(first.getTerminator())) {
64 llvm::dbgs() <<
"the first block has to "
65 "be terminated by a cf.br operation\n";
70 if (
auto wait = dyn_cast<llhd::WaitOp>(last.getTerminator())) {
74 llvm::dbgs() <<
"llhd.wait terminators with optional time "
75 "argument cannot be lowered to structural LLHD\n";
80 SmallVector<Value> observedSignals;
81 for (Value obs : wait.getObserved())
82 if (
auto prb = obs.getDefiningOp<llhd::PrbOp>())
83 if (!op.getBody().isAncestor(prb->getParentRegion()))
84 observedSignals.push_back(prb.getSignal());
88 WalkResult result = op.walk([&](Operation *operation) -> WalkResult {
91 for (Value operand : operation->getOperands()) {
92 if (op.getBody().isAncestor(operand.getParentRegion()))
94 if (llvm::is_contained(wait.getObserved(), operand))
96 if (llvm::is_contained(observedSignals, operand))
98 if (auto *defOp = operand.getDefiningOp();
99 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
101 if (auto bitcastOp = operand.getDefiningOp<hw::BitcastOp>())
102 if (auto *defOp = bitcastOp.getInput().getDefiningOp();
103 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
107 llvm::dbgs() <<
"the wait terminator is required to "
108 "have values used in the process as arguments\n";
113 return WalkResult::advance();
116 return failure(result.wasInterrupted());
120 llvm::dbgs() <<
"the second block must be "
121 "terminated by llhd.wait\n";
126 void ProcessLoweringPass::runOnOperation() {
127 ModuleOp module = getOperation();
129 module.walk([](llhd::ProcessOp op) {
130 LLVM_DEBUG({ llvm::dbgs() <<
"\n=== Process\n"; });
132 if (failed(isProcValidToLower(op)))
138 if (op.getBody().getBlocks().size() == 2) {
139 Block &first = op.getBody().front();
140 Block &second = op.getBody().back();
142 first.getTerminator()->erase();
144 first.getOperations().splice(first.end(), second.getOperations());
146 second.dropAllReferences();
147 second.dropAllDefinedValueUses();
152 op.getBody().front().getTerminator()->erase();
154 IRRewriter rewriter(op);
155 rewriter.inlineBlockBefore(&op.getBody().front(), op);
158 LLVM_DEBUG({ llvm::dbgs() <<
"Process lowered successfully!\n"; });
163 std::unique_ptr<OperationPass<ModuleOp>>
165 return std::make_unique<ProcessLoweringPass>();
std::unique_ptr< OperationPass< ModuleOp > > createProcessLoweringPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.