CIRCT  20.0.0git
Sig2RegPass.cpp
Go to the documentation of this file.
1 //===- Sig2RegPass.cpp - Implement the Sig2Reg Pass -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implement Pass to promote LLHD signals to SSA values.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "circt/Dialect/HW/HWOps.h"
16 #include "llvm/Support/Debug.h"
17 
18 #define DEBUG_TYPE "llhd-sig2reg"
19 
20 namespace circt {
21 namespace llhd {
22 #define GEN_PASS_DEF_SIG2REG
23 #include "circt/Dialect/LLHD/Transforms/Passes.h.inc"
24 } // namespace llhd
25 } // namespace circt
26 
27 using namespace mlir;
28 using namespace circt;
29 
30 namespace {
31 struct Sig2RegPass : public circt::llhd::impl::Sig2RegBase<Sig2RegPass> {
32  void runOnOperation() override;
33 };
34 } // namespace
35 
36 static LogicalResult promote(llhd::SignalOp sigOp) {
37  SmallVector<llhd::PrbOp> probes;
38  llhd::DrvOp driveOp;
39  for (auto *user : sigOp.getResult().getUsers()) {
40  if (user->getBlock() != sigOp->getBlock()) {
41  LLVM_DEBUG(
42  { llvm::dbgs() << "Promotion failed: user in other block\n"; });
43  return failure();
44  }
45 
46  if (auto prbOp = dyn_cast<llhd::PrbOp>(user)) {
47  probes.push_back(prbOp);
48  continue;
49  }
50 
51  if (auto drvOp = dyn_cast<llhd::DrvOp>(user)) {
52  if (driveOp) {
53  LLVM_DEBUG({ llvm::dbgs() << "Promotion failed: multiple drivers\n"; });
54  return failure();
55  }
56 
57  if (drvOp.getEnable()) {
58  LLVM_DEBUG(
59  { llvm::dbgs() << "Promotion failed: conditional driver\n"; });
60  return failure();
61  }
62 
63  driveOp = drvOp;
64  continue;
65  }
66 
67  LLVM_DEBUG({
68  llvm::dbgs() << "Promotion failed: user that is not a probe or drive: "
69  << *user << "\n";
70  });
71  return failure();
72  }
73 
74  Value replacement;
75  if (driveOp) {
76  auto timeOp = driveOp.getTime().getDefiningOp<llhd::ConstantTimeOp>();
77  if (!timeOp)
78  return failure();
79 
80  OpBuilder builder(driveOp);
81  if (timeOp.getValue().getTime() == 0 && timeOp.getValue().getDelta() == 0)
82  replacement = driveOp.getValue();
83  else
84  replacement = builder.create<llhd::DelayOp>(
85  driveOp.getLoc(), driveOp.getValue(), timeOp.getValue());
86  } else {
87  replacement = sigOp.getInit();
88  }
89 
90  for (auto prb : probes) {
91  prb.getResult().replaceAllUsesWith(replacement);
92  prb.erase();
93  }
94 
95  if (driveOp)
96  driveOp.erase();
97 
98  return success();
99 }
100 
101 void Sig2RegPass::runOnOperation() {
102  hw::HWModuleOp moduleOp = getOperation();
103 
104  for (auto sigOp :
105  llvm::make_early_inc_range(moduleOp.getOps<llhd::SignalOp>())) {
106  LLVM_DEBUG(
107  { llvm::dbgs() << "\nAttempting to promote " << sigOp << "\n"; });
108  if (failed(promote(sigOp)))
109  continue;
110 
111  LLVM_DEBUG({ llvm::dbgs() << "Successfully promoted!\n"; });
112  sigOp.erase();
113  }
114 }
static LogicalResult promote(llhd::SignalOp sigOp)
Definition: Sig2RegPass.cpp:36
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21