Skip to content

Commit a013bc2

Browse files
address comments
1 parent c1b8c55 commit a013bc2

File tree

4 files changed

+53
-30
lines changed

4 files changed

+53
-30
lines changed

mlir/include/mlir/Transforms/Passes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ def RemoveDeadValues : Pass<"remove-dead-values"> {
248248
```
249249
}];
250250
let constructor = "mlir::createRemoveDeadValuesPass()";
251+
let dependentDialects = ["ub::UBDialect"];
251252
}
252253

253254
def PrintIRPass : Pass<"print-ir"> {

mlir/lib/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ add_mlir_library(MLIRTransforms
3939
MLIRSideEffectInterfaces
4040
MLIRSupport
4141
MLIRTransformUtils
42+
MLIRUBDialect
4243
)

mlir/lib/Transforms/RemoveDeadValues.cpp

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
3535
#include "mlir/Analysis/DataFlow/LivenessAnalysis.h"
36+
#include "mlir/Dialect/UB/IR/UBOps.h"
3637
#include "mlir/IR/Builders.h"
3738
#include "mlir/IR/BuiltinAttributes.h"
3839
#include "mlir/IR/Dialect.h"
@@ -141,33 +142,6 @@ static bool hasLive(ValueRange values, const DenseSet<Value> &nonLiveSet,
141142
return false;
142143
}
143144

144-
/// Return true iff at least one value in `values` is dead, given the liveness
145-
/// information in `la`.
146-
static bool hasDead(ValueRange values, const DenseSet<Value> &nonLiveSet,
147-
RunLivenessAnalysis &la) {
148-
for (Value value : values) {
149-
if (nonLiveSet.contains(value)) {
150-
LDBG() << "Value " << value << " is already marked non-live (dead)";
151-
return true;
152-
}
153-
154-
const Liveness *liveness = la.getLiveness(value);
155-
if (!liveness) {
156-
LDBG() << "Value " << value
157-
<< " has no liveness info, conservatively considered live";
158-
continue;
159-
}
160-
if (liveness->isLive) {
161-
LDBG() << "Value " << value << " is live according to liveness analysis";
162-
continue;
163-
} else {
164-
LDBG() << "Value " << value << " is dead according to liveness analysis";
165-
return true;
166-
}
167-
}
168-
return false;
169-
}
170-
171145
/// Return a BitVector of size `values.size()` where its i-th bit is 1 iff the
172146
/// i-th value in `values` is live, given the liveness information in `la`.
173147
static BitVector markLives(ValueRange values, const DenseSet<Value> &nonLiveSet,
@@ -287,7 +261,12 @@ static SmallVector<OpOperand *> operandsToOpOperands(OperandRange operands) {
287261
static void processSimpleOp(Operation *op, RunLivenessAnalysis &la,
288262
DenseSet<Value> &nonLiveSet,
289263
RDVFinalCleanupList &cl) {
290-
if (hasDead(op->getOperands(), nonLiveSet, la)) {
264+
// Operations that have dead operands can be erased regardless of their
265+
// side effects. The liveness analysis would not have marked an SSA value as
266+
// "dead" if it had a side-effecting user that is reachable.
267+
bool hasDeadOperand =
268+
markLives(op->getOperands(), nonLiveSet, la).flip().any();
269+
if (hasDeadOperand) {
291270
LDBG() << "Simple op has dead operands, so the op must be dead: "
292271
<< OpWithFlags(op, OpPrintingFlags().skipRegions());
293272
assert(!hasLive(op->getResults(), nonLiveSet, la) &&
@@ -399,6 +378,8 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module,
399378
// block other than the entry block, because every block has a terminator.
400379
for (Block &block : funcOp.getBlocks()) {
401380
Operation *returnOp = block.getTerminator();
381+
if (!returnOp->hasTrait<OpTrait::ReturnLike>())
382+
continue;
402383
if (returnOp && returnOp->getNumOperands() == numReturns)
403384
cl.operands.push_back({returnOp, nonLiveRets});
404385
}
@@ -738,7 +719,11 @@ static void processRegionBranchOp(RegionBranchOpInterface regionBranchOp,
738719
}
739720

740721
/// Steps to process a `BranchOpInterface` operation:
741-
/// Iterate through each successor block of `branchOp`.
722+
///
723+
/// When a non-forwarded operand is dead (e.g., the condition value of a
724+
/// conditional branch op), the entire operation is dead.
725+
///
726+
/// Otherwise, iterate through each successor block of `branchOp`.
742727
/// (1) For each successor block, gather all operands from all successors.
743728
/// (2) Fetch their associated liveness analysis data and collect for future
744729
/// removal.
@@ -749,7 +734,22 @@ static void processBranchOp(BranchOpInterface branchOp, RunLivenessAnalysis &la,
749734
DenseSet<Value> &nonLiveSet,
750735
RDVFinalCleanupList &cl) {
751736
LDBG() << "Processing branch op: " << *branchOp;
737+
738+
// Check for dead non-forwarded operands.
739+
BitVector deadNonForwardedOperands =
740+
markLives(branchOp->getOperands(), nonLiveSet, la).flip();
752741
unsigned numSuccessors = branchOp->getNumSuccessors();
742+
for (unsigned succIdx = 0; succIdx < numSuccessors; ++succIdx) {
743+
SuccessorOperands successorOperands =
744+
branchOp.getSuccessorOperands(succIdx);
745+
// Remove all non-forwarded operands from the bit vector.
746+
for (OpOperand &opOperand : successorOperands.getMutableForwardedOperands())
747+
deadNonForwardedOperands[opOperand.getOperandNumber()] = false;
748+
}
749+
if (deadNonForwardedOperands.any()) {
750+
cl.operations.push_back(branchOp.getOperation());
751+
return;
752+
}
753753

754754
for (unsigned succIdx = 0; succIdx < numSuccessors; ++succIdx) {
755755
Block *successorBlock = branchOp->getSuccessor(succIdx);
@@ -824,9 +824,14 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
824824

825825
// 3. Operations
826826
LDBG() << "Cleaning up " << list.operations.size() << " operations";
827-
for (auto &op : list.operations) {
827+
for (Operation *op : list.operations) {
828828
LDBG() << "Erasing operation: "
829829
<< OpWithFlags(op, OpPrintingFlags().skipRegions());
830+
if (op->hasTrait<OpTrait::IsTerminator>()) {
831+
// When erasing a terminator, insert an unreachable op in its place.
832+
OpBuilder b(op);
833+
ub::UnreachableOp::create(b, op->getLoc());
834+
}
830835
op->dropAllUses();
831836
op->erase();
832837
}

mlir/test/Transforms/remove-dead-values.mlir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,3 +698,19 @@ func.func @op_block_have_dead_arg(%arg0: index, %arg1: index, %arg2: i1) {
698698
// CHECK-NEXT: return
699699
return
700700
}
701+
702+
// -----
703+
704+
// CHECK-LABEL: func private @remove_dead_branch_op()
705+
// CHECK-NEXT: ub.unreachable
706+
// CHECK-NEXT: ^{{.*}}:
707+
// CHECK-NEXT: return
708+
// CHECK-NEXT: ^{{.*}}:
709+
// CHECK-NEXT: return
710+
func.func private @remove_dead_branch_op(%c: i1, %arg0: i64, %arg1: i64) -> (i64) {
711+
cf.cond_br %c, ^bb1, ^bb2
712+
^bb1:
713+
return %arg0 : i64
714+
^bb2:
715+
return %arg1 : i64
716+
}

0 commit comments

Comments
 (0)