mirror of https://github.com/llvm/circt.git
[circt-reduce] Replace PortPruner with RemoveUnusedPortsPass (#2591)
This commit adds RemoveUnusedPortsPass to reduction passes and replaces PortPruner with RemoveUnusedPortsPass. RemoveUnusedPortsPass would be more powerfull since it prunus ports interprocedurally.
This commit is contained in:
parent
142fc24bf4
commit
6791a4f427
|
@ -1,11 +1,11 @@
|
|||
// RUN: circt-reduce %s --test %S/test.sh --test-arg cat --test-arg "firrtl.module @Bar" --keep-best=0 --include port-pruner | FileCheck %s
|
||||
// RUN: circt-reduce %s --test %S/test.sh --test-arg cat --test-arg "firrtl.module @Bar" --keep-best=0 --include firrtl-remove-unused-ports | FileCheck %s
|
||||
|
||||
firrtl.circuit "Foo" {
|
||||
// CHECK-LABEL: firrtl.module @Foo
|
||||
firrtl.module @Foo(in %x: !firrtl.uint<1>, out %y: !firrtl.uint<3>) {
|
||||
// CHECK: %bar_a = firrtl.wire
|
||||
// CHECK: %bar_c = firrtl.wire
|
||||
// CHECK: %bar_e = firrtl.wire
|
||||
// CHECK-NOT: %bar_a
|
||||
// CHECK-NOT: %bar_c
|
||||
// CHECK-NOT: %bar_e
|
||||
// CHECK: %bar_b, %bar_d = firrtl.instance bar @Bar
|
||||
%bar_a, %bar_b, %bar_c, %bar_d, %bar_e = firrtl.instance bar @Bar (in a: !firrtl.uint<1>, in b: !firrtl.uint<1>, out c: !firrtl.uint<1>, out d: !firrtl.uint<1>, out e: !firrtl.uint<1>)
|
||||
firrtl.connect %bar_a, %x : !firrtl.uint<1>, !firrtl.uint<1>
|
||||
|
|
|
@ -353,11 +353,6 @@ static void pruneUnusedOps(Operation *initialOp) {
|
|||
}
|
||||
}
|
||||
|
||||
static void pruneUnusedOps(Value value) {
|
||||
if (auto *op = value.getDefiningOp())
|
||||
pruneUnusedOps(op);
|
||||
}
|
||||
|
||||
/// Check whether an operation interacts with flows in any way, which can make
|
||||
/// replacement and operand forwarding harder in some cases.
|
||||
static bool isFlowSensitiveOp(Operation *op) {
|
||||
|
@ -484,87 +479,6 @@ struct OperationPruner : public Reduction {
|
|||
SymbolCache symbols;
|
||||
};
|
||||
|
||||
/// A sample reduction pattern that removes ports from FIRRTL modules if they
|
||||
/// are either unused inputs or outputs that are only invalidated.
|
||||
struct PortPruner : public Reduction {
|
||||
void beforeReduction(mlir::ModuleOp op) override { symbols.clear(); }
|
||||
|
||||
bool match(Operation *op) override {
|
||||
auto moduleOp = dyn_cast<firrtl::FModuleOp>(op);
|
||||
return moduleOp && llvm::any_of(moduleOp.getArguments(), onlyInvalidated);
|
||||
}
|
||||
|
||||
LogicalResult rewrite(Operation *op) override {
|
||||
auto moduleOp = cast<firrtl::FModuleOp>(op);
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< "Pruning ports of `" << moduleOp.getName() << "`\n");
|
||||
|
||||
// Make a list of ports we can likely remove.
|
||||
SmallVector<unsigned> removable;
|
||||
for (unsigned i = 0, e = moduleOp.getNumPorts(); i != e; ++i)
|
||||
if (onlyInvalidated(moduleOp.getArgument(i)))
|
||||
removable.push_back(i);
|
||||
assert(!removable.empty() &&
|
||||
"shouldn't work on module with no prunable ports");
|
||||
|
||||
// Erase any users of the ports we are going to remove.
|
||||
for (auto argIdx : removable) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Removing port `"
|
||||
<< moduleOp.getPortName(argIdx) << "`\n");
|
||||
SmallVector<Value> maybeUnused;
|
||||
for (auto *userOp : llvm::make_early_inc_range(
|
||||
moduleOp.getArgument(argIdx).getUsers())) {
|
||||
maybeUnused.append(userOp->operand_begin(), userOp->operand_end());
|
||||
userOp->erase();
|
||||
}
|
||||
for (auto v : maybeUnused)
|
||||
pruneUnusedOps(v);
|
||||
}
|
||||
|
||||
// Actually remove the ports.
|
||||
moduleOp.erasePorts(removable);
|
||||
|
||||
// Update all instances of this module to reflect the change.
|
||||
for (auto *userOp :
|
||||
symbols.getNearestSymbolUserMap(moduleOp).getUsers(moduleOp)) {
|
||||
auto instOp = dyn_cast<firrtl::InstanceOp>(userOp);
|
||||
if (!instOp || instOp.moduleName() != moduleOp.getName())
|
||||
continue;
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< " - Updating instance `" << instOp.name()
|
||||
<< "` in module `"
|
||||
<< instOp->getParentOfType<firrtl::FModuleOp>().getName()
|
||||
<< "`\n");
|
||||
|
||||
// Replace the removed instance port uses with corresponding wire
|
||||
// declarations, and invalidate the output fields.
|
||||
ImplicitLocOpBuilder builder(instOp.getLoc(), instOp);
|
||||
SmallDenseMap<Type, Value, 8> invalidCache;
|
||||
for (auto i : removable) {
|
||||
auto result = instOp.getResult(i);
|
||||
auto name = builder.getStringAttr(Twine(instOp.name()) + "_" +
|
||||
instOp.getPortNameStr(i));
|
||||
auto wire = builder.create<firrtl::WireOp>(
|
||||
result.getType(), name, instOp.getPortAnnotation(i), StringAttr{});
|
||||
invalidateOutputs(builder, wire, invalidCache,
|
||||
instOp.getPortDirection(i) == firrtl::Direction::In);
|
||||
result.replaceAllUsesWith(wire);
|
||||
}
|
||||
|
||||
// Remove the ports from the instance, which creates a new instance op and
|
||||
// we can remove the old one.
|
||||
instOp.erasePorts(builder, removable);
|
||||
instOp->erase();
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
std::string getName() const override { return "port-pruner"; }
|
||||
bool acceptSizeIncrease() const override { return true; }
|
||||
|
||||
SymbolCache symbols;
|
||||
};
|
||||
|
||||
/// A sample reduction pattern that removes FIRRTL annotations from ports and
|
||||
/// operations.
|
||||
struct AnnotationRemover : public Reduction {
|
||||
|
@ -750,6 +664,8 @@ void circt::createAllReductions(
|
|||
add(std::make_unique<PassReduction>(context, firrtl::createInlinerPass()));
|
||||
add(std::make_unique<PassReduction>(context,
|
||||
createSimpleCanonicalizerPass()));
|
||||
add(std::make_unique<PassReduction>(context,
|
||||
firrtl::createRemoveUnusedPortsPass()));
|
||||
add(std::make_unique<InstanceStubber>());
|
||||
add(std::make_unique<MemoryStubber>());
|
||||
add(std::make_unique<ModuleExternalizer>());
|
||||
|
@ -760,7 +676,6 @@ void circt::createAllReductions(
|
|||
add(std::make_unique<OperandForwarder<1>>());
|
||||
add(std::make_unique<OperandForwarder<2>>());
|
||||
add(std::make_unique<OperationPruner>());
|
||||
add(std::make_unique<PortPruner>());
|
||||
add(std::make_unique<AnnotationRemover>());
|
||||
add(std::make_unique<RootPortPruner>());
|
||||
add(std::make_unique<ExtmoduleInstanceRemover>());
|
||||
|
|
Loading…
Reference in New Issue