Skip to content

Commit

Permalink
[FIRRTL][IMDCE] Remove dead Invalid Value op (#4996)
Browse files Browse the repository at this point in the history
We've changed the modeling of InvalidValueOp to have side-effect so 
it's necessary to handle invalid values specially. Since InvalidValueOp has
MemAlloc side-effects trait, this PR allows dead operations with 
known side-effects(Alloc/Read) to be removed.
  • Loading branch information
uenoku authored Apr 11, 2023
1 parent ab5a748 commit 40bdb08
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
15 changes: 12 additions & 3 deletions lib/Dialect/FIRRTL/Transforms/IMDeadCodeElim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "circt/Dialect/FIRRTL/Passes.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/IR/Threading.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/TinyPtrVector.h"
Expand All @@ -21,6 +22,13 @@
using namespace circt;
using namespace firrtl;

// Return true if this op has side-effects except for alloc and read.
static bool hasUnknownSideEffect(Operation *op) {
return !(mlir::isMemoryEffectFree(op) ||
mlir::hasSingleEffect<mlir::MemoryEffects::Allocate>(op) ||
mlir::hasSingleEffect<mlir::MemoryEffects::Read>(op));
}

/// Return true if this is a wire or a register or a node.
static bool isDeclaration(Operation *op) {
return isa<WireOp, RegResetOp, RegOp, NodeOp, MemOp>(op);
Expand Down Expand Up @@ -202,7 +210,7 @@ void IMDeadCodeElimPass::markBlockExecutable(Block *block) {
else if (isa<FConnectLike>(op))
// Skip connect op.
continue;
else if (!mlir::isMemoryEffectFree(&op))
else if (hasUnknownSideEffect(&op))
markUnknownSideEffectOp(&op);

// TODO: Handle attach etc.
Expand Down Expand Up @@ -389,8 +397,9 @@ void IMDeadCodeElimPass::rewriteModuleBody(FModuleOp module) {
continue;
}

// Delete dead wires, regs and nodes.
if (isDeclaration(&op) && isAssumedDead(&op)) {
// Delete dead wires, regs, nodes and alloc/read ops.
if ((isDeclaration(&op) || !hasUnknownSideEffect(&op)) &&
isAssumedDead(&op)) {
LLVM_DEBUG(llvm::dbgs() << "DEAD: " << op << "\n";);
assert(op.use_empty() && "users should be already removed");
op.erase();
Expand Down
6 changes: 6 additions & 0 deletions test/Dialect/FIRRTL/imdce.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ firrtl.circuit "DeadInputPort" {
// -----

firrtl.circuit "DeleteInstance" {
// CHECK-NOT: @InvalidValue
firrtl.module private @InvalidValue() {
%invalid_ui289 = firrtl.invalidvalue : !firrtl.uint<289>
}
firrtl.module private @SideEffect1(in %a: !firrtl.uint<1>, in %clock: !firrtl.clock) {
firrtl.printf %clock, %a, "foo" : !firrtl.clock, !firrtl.uint<1>
}
Expand All @@ -334,6 +338,8 @@ firrtl.circuit "DeleteInstance" {
}
// CHECK-LABEL: DeleteInstance
firrtl.module @DeleteInstance(in %a: !firrtl.uint<1>, in %clock: !firrtl.clock, out %b: !firrtl.uint<1>) {
// CHECK-NOT: inv
firrtl.instance inv @InvalidValue()
// CHECK-NOT: p1
// CHECK: instance p2 @PassThrough
// CHECK-NEXT: instance s @SideEffect2
Expand Down

0 comments on commit 40bdb08

Please sign in to comment.