llvm / llvm/llvm-project

[MLIR] `remove-dead-values` produce invalid IR for dead block argument with mixed-liveness predecessors

Open
#217,015 4 comments 0 reactions 0 assignees View on GitHub
mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

`remove-dead-values` can produce invalid IR when a dead successor block argument has multiple predecessors whose incoming values have different liveness.

### Input Program

**input.mlir**

```llvm
module {
func.func @multi_pred_mixed(%arg0: i1, %arg1: i32) -> i32 {
%c0_i32 = arith.constant 0 : i32
cf.cond_br %arg0, ^bb1, ^bb2
^bb1: // pred: ^bb0
cf.br ^bb3(%c0_i32 : i32)
^bb2: // pred: ^bb0
cf.br ^bb3(%arg1 : i32)
^bb3(%0: i32): // 2 preds: ^bb1, ^bb2
return %arg1 : i32
}
}
```

### Current Result
```bash
input.mlir:10:5: error: branch has 1 operands for successor #0, but target block has 0
cf.br ^join(%x : i32)
^
input.mlir:10:5: note: see current operation: "cf.br"(%arg1)[^bb3] : (i32) -> ()
```
`%arg` is unused, so the pass removes the block argument. But it only removes the corresponding operand from one predecessor, leaving the other branch still passing an operand to a block with no arguments.

Expected behavior: produce valid IR

Version: ef88536bbf62469eb2396d719d237b3191cf4843

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the input.mlir example and tracing the remove-dead-values pass as it handles the dead block argument and both predecessors. Verify that the resulting IR is valid and that every predecessor's operands match the target block arguments.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.