[Mlir-commits] [mlir] [MLIR] Fix remove-dead-values missing dead block arguments (PR #216652)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Aug 17 00:55:50 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core
Author: Aayush Shrivastava (iamaayushrivastava)
<details>
<summary>Changes</summary>
Fixes #<!-- -->216644
In `processBranchOp` (`mlir/lib/Transforms/RemoveDeadValues.cpp`), the liveness of a `cf.br` successor's block argument was computed from the liveness of the caller-side operand value being forwarded to it, not from the block argument itself. When the forwarded value happened to be live for an unrelated reason (here, `%arg0` is both passed to `cf.br` and directly returned), the block argument incorrectly inherited that liveness and was never recognized as dead. The fix computes `successorNonLive` from `successorBlock->getArguments()` directly, which correctly reflects whether the argument is used inside its own block.
---
Full diff: https://github.com/llvm/llvm-project/pull/216652.diff
2 Files Affected:
- (modified) mlir/lib/Transforms/RemoveDeadValues.cpp (+11-16)
- (modified) mlir/test/Transforms/remove-dead-values.mlir (+18)
``````````diff
diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp
index 6e55bc390be23..3ea0f5f642365 100644
--- a/mlir/lib/Transforms/RemoveDeadValues.cpp
+++ b/mlir/lib/Transforms/RemoveDeadValues.cpp
@@ -465,10 +465,9 @@ static void processRegionBranchOp(RegionBranchOpInterface regionBranchOp,
/// conditional branch op), the entire operation is dead.
///
/// Otherwise, iterate through each successor block of `branchOp`.
-/// (1) For each successor block, gather all operands from all successors.
-/// (2) Fetch their associated liveness analysis data and collect for future
-/// removal.
-/// (3) Identify and collect the dead operands from the successor block
+/// (1) For each successor block, fetch the liveness analysis data of its
+/// block arguments and collect for future removal.
+/// (2) Identify and collect the dead operands from the successor block
/// as well as their corresponding arguments.
static void processBranchOp(BranchOpInterface branchOp, RunLivenessAnalysis &la,
@@ -495,22 +494,18 @@ static void processBranchOp(BranchOpInterface branchOp, RunLivenessAnalysis &la,
for (unsigned succIdx = 0; succIdx < numSuccessors; ++succIdx) {
Block *successorBlock = branchOp->getSuccessor(succIdx);
- // Do (1)
- SuccessorOperands successorOperands =
- branchOp.getSuccessorOperands(succIdx);
- SmallVector<Value> operandValues;
- for (unsigned operandIdx = 0; operandIdx < successorOperands.size();
- ++operandIdx) {
- operandValues.push_back(successorOperands[operandIdx]);
- }
-
- // Do (2)
+ // Do (1). Liveness of a successor block argument must be determined
+ // from the argument itself (i.e. whether it is used inside the
+ // successor block), not from the liveness of the operand value being
+ // forwarded to it. The forwarded operand value may well be live for
+ // unrelated reasons (e.g. it is also used elsewhere), which must not
+ // prevent the block argument from being recognized as dead.
BitVector successorNonLive =
- markLives(operandValues, nonLiveSet, la).flip();
+ markLives(successorBlock->getArguments(), nonLiveSet, la).flip();
collectNonLiveValues(nonLiveSet, successorBlock->getArguments(),
successorNonLive);
- // Do (3)
+ // Do (2)
cl.blocks.push_back({successorBlock, successorNonLive});
cl.successorOperands.push_back({branchOp, succIdx, successorNonLive});
}
diff --git a/mlir/test/Transforms/remove-dead-values.mlir b/mlir/test/Transforms/remove-dead-values.mlir
index 390a448060b7f..bca692699225c 100644
--- a/mlir/test/Transforms/remove-dead-values.mlir
+++ b/mlir/test/Transforms/remove-dead-values.mlir
@@ -895,3 +895,21 @@ module @func_with_non_call_users {
}
spirv.EntryPoint "GLCompute" @callee
}
+
+// -----
+
+// A dead successor block argument must be removed even when the value
+// forwarded to it is itself live for an unrelated reason (here, %arg0 is
+// also returned directly). Fixes #216644.
+//
+// CHECK-LABEL: func.func @dead_block_arg_with_live_forwarded_operand
+// CHECK-SAME: (%[[arg0:.*]]: i32) -> i32
+// CHECK: cf.br ^[[BB1:bb[0-9]+]]
+// CHECK-NOT: i32
+// CHECK: ^[[BB1]]:
+// CHECK-NEXT: return %[[arg0]] : i32
+func.func @dead_block_arg_with_live_forwarded_operand(%arg0: i32) -> i32 {
+ cf.br ^bb1(%arg0 : i32)
+^bb1(%0: i32):
+ return %arg0 : i32
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/216652
More information about the Mlir-commits
mailing list