CIRCT 23.0.0git
Loading...
Searching...
No Matches
EliminateWires.cpp
Go to the documentation of this file.
1//===- EliminateWires.cpp - Eliminate useless wires -------------*- C++ -*-===//
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// This file defines the EliminateWires pass. This pass finds wires which,
10// when relocated, become unnecessary and eliminates them. This is done by
11// creating a node between the write and readers. Using a node allows the pass
12// to preserve inner symbols and probes, letting CSE remove useless nodes.
13//
14//===----------------------------------------------------------------------===//
15
19#include "circt/Support/Debug.h"
20#include "mlir/IR/Dominance.h"
21#include "mlir/IR/ImplicitLocOpBuilder.h"
22#include "mlir/Pass/Pass.h"
23#include "llvm/Support/Debug.h"
24
25#include <deque>
26
27#define DEBUG_TYPE "firrtl-eliminate-wires"
28
29namespace circt {
30namespace firrtl {
31#define GEN_PASS_DEF_ELIMINATEWIRES
32#include "circt/Dialect/FIRRTL/Passes.h.inc"
33} // namespace firrtl
34} // namespace circt
35
36using namespace circt;
37using namespace firrtl;
38
39//===----------------------------------------------------------------------===//
40// Pass Infrastructure
41//===----------------------------------------------------------------------===//
42
43namespace {
44struct EliminateWiresPass
45 : public circt::firrtl::impl::EliminateWiresBase<EliminateWiresPass> {
46 void runOnOperation() override;
47};
48} // end anonymous namespace
49
50void EliminateWiresPass::runOnOperation() {
52
53 auto module = getOperation();
54 auto &dominance = getAnalysis<mlir::DominanceInfo>();
55
56 std::deque<std::pair<WireOp, MatchingConnectOp>> worklist;
57
58 for (auto wire : module.getOps<WireOp>()) {
59 auto type = type_dyn_cast<FIRRTLBaseType>(wire.getResult().getType());
60 if (!type || !type.isPassive()) {
61 ++complexTypeWires;
62 continue;
63 }
64 // This will fail if there are multiple connects (due to aggregate
65 // decomposition or whens) or if there are connects in blocks (due to whens
66 // or matches). We are fine with this, we don't want to reason about those
67 // cases as other passes will handle them.
68 auto writer = getSingleConnectUserOf(wire.getResult());
69 if (!writer) {
70 ++complexWriteWires;
71 continue;
72 }
73 bool safe = true;
74 for (auto *user : wire->getUsers()) {
75 if (!dominance.dominates(writer, user)) {
76 ++notDomWires;
77 safe = false;
78 break;
79 }
80 }
81 if (!safe)
82 continue;
83 worklist.emplace_back(wire, writer);
84 }
85
86 for (auto [wire, writer] : worklist) {
87 mlir::ImplicitLocOpBuilder builder(wire->getLoc(), writer);
88 auto node = NodeOp::create(builder, writer.getSrc(), wire.getName(),
89 wire.getNameKind(), wire.getAnnotations(),
90 wire.getInnerSymAttr(), wire.getForceable());
91 sv::setSVAttributes(node, sv::getSVAttributes(wire));
92 wire.replaceAllUsesWith(node);
93 wire.erase();
94 writer.erase();
95 ++erasedWires;
96 }
97}
#define CIRCT_DEBUG_SCOPED_PASS_LOGGER(PASS)
Definition Debug.h:70
MatchingConnectOp getSingleConnectUserOf(Value value)
Scan all the uses of the specified value, checking to see if there is exactly one connect that has th...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.