Skip to content

Commit

Permalink
[HW] Add reduction patterns to trim port list of top-level module (#7587
Browse files Browse the repository at this point in the history
)
  • Loading branch information
maerhart authored Sep 16, 2024
1 parent 478e0db commit 5aba666
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 57 deletions.
80 changes: 80 additions & 0 deletions lib/Dialect/HW/HWReductions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,83 @@ struct HWConstantifier : public Reduction {
std::string getName() const override { return "hw-constantifier"; }
};

/// Remove the first or last output of the top-level module depending on the
/// 'Front' template parameter.
template <bool Front>
struct ModuleOutputPruner : public OpReduction<HWModuleOp> {
void beforeReduction(mlir::ModuleOp op) override {
useEmpty.clear();

SymbolTableCollection table;
SymbolUserMap users(table, op);
for (auto module : op.getOps<HWModuleOp>())
if (users.useEmpty(module))
useEmpty.insert(module);
}

uint64_t match(HWModuleOp op) override {
return op.getNumOutputPorts() != 0 && useEmpty.contains(op);
}

LogicalResult rewrite(HWModuleOp op) override {
Operation *terminator = op.getBody().front().getTerminator();
auto operands = terminator->getOperands();
ValueRange newOutputs = operands.drop_back();
unsigned portToErase = op.getNumOutputPorts() - 1;
if (Front) {
newOutputs = operands.drop_front();
portToErase = 0;
}

terminator->setOperands(newOutputs);
op.erasePorts({}, {portToErase});

return success();
}

std::string getName() const override {
return Front ? "hw-module-output-pruner-front"
: "hw-module-output-pruner-back";
}

DenseSet<HWModuleOp> useEmpty;
};

/// Remove all input ports of the top-level module that have no users
struct ModuleInputPruner : public OpReduction<HWModuleOp> {
void beforeReduction(mlir::ModuleOp op) override {
useEmpty.clear();

SymbolTableCollection table;
SymbolUserMap users(table, op);
for (auto module : op.getOps<HWModuleOp>())
if (users.useEmpty(module))
useEmpty.insert(module);
}

uint64_t match(HWModuleOp op) override { return useEmpty.contains(op); }

LogicalResult rewrite(HWModuleOp op) override {
SmallVector<unsigned> inputsToErase;
BitVector toErase(op.getNumPorts());
for (auto [i, arg] : llvm::enumerate(op.getBody().getArguments())) {
if (arg.use_empty()) {
toErase.set(i);
inputsToErase.push_back(i);
}
}

op.erasePorts(inputsToErase, {});
op.getBodyBlock()->eraseArguments(toErase);

return success();
}

std::string getName() const override { return "hw-module-input-pruner"; }

DenseSet<HWModuleOp> useEmpty;
};

//===----------------------------------------------------------------------===//
// Reduction Registration
//===----------------------------------------------------------------------===//
Expand All @@ -151,6 +228,9 @@ void HWReducePatternDialectInterface::populateReducePatterns(
patterns.add<HWOperandForwarder<0>, 4>();
patterns.add<HWOperandForwarder<1>, 3>();
patterns.add<HWOperandForwarder<2>, 2>();
patterns.add<ModuleOutputPruner<true>, 2>();
patterns.add<ModuleOutputPruner<false>, 2>();
patterns.add<ModuleInputPruner, 2>();
}

void hw::registerReducePatternDialectInterface(
Expand Down
20 changes: 7 additions & 13 deletions test/Dialect/Arc/Reduction/pattern-registration.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,13 @@

// RUN: circt-reduce %s --test /usr/bin/env --test-arg cat --list | FileCheck %s

// CHECK: hw-
// CHECK: hw-
// CHECK: hw-
// CHECK-NEXT: arc-strip-sv
// CHECK-NEXT: cse
// CHECK-NEXT: hw-
// CHECK-NEXT: arc-dedup
// CHECK-NEXT: canonicalize
// CHECK-NEXT: hw-
// CHECK-NEXT: arc-state-elimination
// CHECK-NEXT: operation-pruner
// CHECK-NEXT: arc-canonicalizer
// CHECK-EMPTY:
// CHECK-DAG: arc-strip-sv
// CHECK-DAG: cse
// CHECK-DAG: arc-dedup
// CHECK-DAG: canonicalize
// CHECK-DAG: arc-state-elimination
// CHECK-DAG: operation-pruner
// CHECK-DAG: arc-canonicalizer
arc.define @DummyArc(%arg0: i32) -> i32 {
arc.output %arg0 : i32
}
Expand Down
70 changes: 35 additions & 35 deletions test/Dialect/FIRRTL/Reduction/pattern-registration.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,41 @@
// RUN: circt-reduce %s --test /usr/bin/env --test-arg cat --list | FileCheck %s

// CHECK: firrtl-lower-chirrtl
// CHECK-NEXT: firrtl-infer-widths
// CHECK-NEXT: firrtl-infer-resets
// CHECK-NEXT: firrtl-module-externalizer
// CHECK-NEXT: instance-stubber
// CHECK-NEXT: memory-stubber
// CHECK-NEXT: eager-inliner
// CHECK-NEXT: firrtl-lower-types
// CHECK-NEXT: firrtl-expand-whens
// CHECK-NEXT: firrtl-inliner
// CHECK-NEXT: firrtl-imconstprop
// CHECK-NEXT: firrtl-remove-unused-ports
// CHECK-NEXT: node-symbol-remover
// CHECK-NEXT: connect-forwarder
// CHECK-NEXT: connect-invalidator
// CHECK-NEXT: firrtl-constantifier
// CHECK-NEXT: firrtl-operand0-forwarder
// CHECK-NEXT: firrtl-operand1-forwarder
// CHECK-NEXT: firrtl-operand2-forwarder
// CHECK-NEXT: detach-subaccesses
// CHECK-NEXT: hw-module-externalizer
// CHECK-NEXT: annotation-remover
// CHECK-NEXT: hw-constantifier
// CHECK-NEXT: root-port-pruner
// CHECK-NEXT: hw-operand0-forwarder
// CHECK-NEXT: extmodule-instance-remover
// CHECK-NEXT: cse
// CHECK-NEXT: hw-operand1-forwarder
// CHECK-NEXT: connect-source-operand-0-forwarder
// CHECK-NEXT: canonicalize
// CHECK-NEXT: hw-operand2-forwarder
// CHECK-NEXT: connect-source-operand-1-forwarder
// CHECK-NEXT: operation-pruner
// CHECK-NEXT: connect-source-operand-2-forwarder
// CHECK-NEXT: module-internal-name-sanitizer
// CHECK-NEXT: module-name-sanitizer
// CHECK-DAG: firrtl-infer-widths
// CHECK-DAG: firrtl-infer-resets
// CHECK-DAG: firrtl-module-externalizer
// CHECK-DAG: instance-stubber
// CHECK-DAG: memory-stubber
// CHECK-DAG: eager-inliner
// CHECK-DAG: firrtl-lower-types
// CHECK-DAG: firrtl-expand-whens
// CHECK-DAG: firrtl-inliner
// CHECK-DAG: firrtl-imconstprop
// CHECK-DAG: firrtl-remove-unused-ports
// CHECK-DAG: node-symbol-remover
// CHECK-DAG: connect-forwarder
// CHECK-DAG: connect-invalidator
// CHECK-DAG: firrtl-constantifier
// CHECK-DAG: firrtl-operand0-forwarder
// CHECK-DAG: firrtl-operand1-forwarder
// CHECK-DAG: firrtl-operand2-forwarder
// CHECK-DAG: detach-subaccesses
// CHECK-DAG: hw-module-externalizer
// CHECK-DAG: annotation-remover
// CHECK-DAG: hw-constantifier
// CHECK-DAG: root-port-pruner
// CHECK-DAG: hw-operand0-forwarder
// CHECK-DAG: extmodule-instance-remover
// CHECK-DAG: cse
// CHECK-DAG: hw-operand1-forwarder
// CHECK-DAG: connect-source-operand-0-forwarder
// CHECK-DAG: canonicalize
// CHECK-DAG: hw-operand2-forwarder
// CHECK-DAG: connect-source-operand-1-forwarder
// CHECK-DAG: operation-pruner
// CHECK-DAG: connect-source-operand-2-forwarder
// CHECK-DAG: module-internal-name-sanitizer
// CHECK-DAG: module-name-sanitizer
// CHECK-EMPTY:
firrtl.circuit "Foo" {
firrtl.module @Foo() {}
Expand Down
9 changes: 9 additions & 0 deletions test/Dialect/HW/Reduction/hw-module-input-pruner.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// UNSUPPORTED: system-windows
// See https://github.com/llvm/circt/issues/4129
// RUN: circt-reduce %s --test /usr/bin/env --test-arg grep --test-arg -q --test-arg "hw.output %arg" --keep-best=0 --include hw-module-input-pruner | FileCheck %s

// CHECK-LABEL: hw.module @Foo(in %arg0 : i32, out out0 : i32)
hw.module @Foo(in %arg0 : i32, in %arg1 : i32, in %arg2 : i32, out out0 : i32) {
// CHECK-NEXT: hw.output %arg0 : i32
hw.output %arg0 : i32
}
12 changes: 12 additions & 0 deletions test/Dialect/HW/Reduction/hw-module-output-pruner.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// UNSUPPORTED: system-windows
// See https://github.com/llvm/circt/issues/4129
// RUN: circt-reduce %s --test /usr/bin/env --test-arg grep --test-arg -q --test-arg "hw.output %arg" --keep-best=0 --include hw-module-output-pruner-back | FileCheck %s --check-prefix=CHECK-BACK
// RUN: circt-reduce %s --test /usr/bin/env --test-arg grep --test-arg -q --test-arg "hw.output %arg" --keep-best=0 --include hw-module-output-pruner-front | FileCheck %s --check-prefix=CHECK-FRONT

// CHECK-FRONT-LABEL: hw.module @Foo(in %arg0 : i32, in %arg1 : i32, in %arg2 : i32, out out2 : i32)
// CHECK-BACK-LABEL: hw.module @Foo(in %arg0 : i32, in %arg1 : i32, in %arg2 : i32, out out0 : i32)
hw.module @Foo(in %arg0 : i32, in %arg1 : i32, in %arg2 : i32, out out0 : i32, out out1 : i32, out out2 : i32) {
// CHECK-FRONT-NEXT: hw.output %arg2 : i32
// CHECK-BACK-NEXT: hw.output %arg0 : i32
hw.output %arg0, %arg1, %arg2 : i32, i32, i32
}
20 changes: 11 additions & 9 deletions test/Dialect/HW/Reduction/pattern-registration.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@

// RUN: circt-reduce %s --test /usr/bin/env --test-arg cat --list | FileCheck %s

// CHECK: hw-module-externalizer
// CHECK-NEXT: hw-constantifier
// CHECK-NEXT: hw-operand0-forwarder
// CHECK-NEXT: cse
// CHECK-NEXT: hw-operand1-forwarder
// CHECK-NEXT: canonicalize
// CHECK-NEXT: hw-operand2-forwarder
// CHECK-NEXT: operation-pruner
// CHECK-EMPTY:
// CHECK-DAG: hw-module-externalizer
// CHECK-DAG: hw-constantifier
// CHECK-DAG: hw-operand0-forwarder
// CHECK-DAG: cse
// CHECK-DAG: hw-operand1-forwarder
// CHECK-DAG: canonicalize
// CHECK-DAG: hw-operand2-forwarder
// CHECK-DAG: hw-module-output-pruner-front
// CHECK-DAG: hw-module-output-pruner-back
// CHECK-DAG: hw-module-input-pruner
// CHECK-DAG: operation-pruner
hw.module @Foo(in %in : i1, out out : i1) {
hw.output %in : i1
}

0 comments on commit 5aba666

Please sign in to comment.