[DebugInfo][CorrelatedValuePropagation] Eliminating `sdiv` leaves a wrong debug value
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Description
`correlated-propagation` eliminates an `sdiv` after proving that its result only affects program behavior when the dividend is strictly between `-42` and `42`. Within that range, `x / 42` is always `0`, so replacing the quotient with zero preserves the program result.
However, the pass also changes the `#dbg_value` for the source variable `quotient` to describe the constant `0`. For inputs outside the inferred range, the source quotient is not necessarily zero even though `quotient` is still a source variable that can be inspected. With `x = 42`, LLDB prints `quotient` as `0` after the pass instead of the source-level value `1`.
## Reproducer
`case.c`:
```c
#include
int sdiv_elide(int x) {
int quotient = x / 42;
bool in_range = (x < 42) && (x > -42);
return in_range ? quotient : 24;
}
int main(void) { return sdiv_elide(42) != 24; }
```
Build pipeline:
```sh
clang -g -O0 -Xclang -disable-O0-optnone -fno-discard-value-names -S -emit-llvm case.c -o case.ll
opt -passes='mem2reg,simplifycfg,instcombine' -S case.ll -o src.ll
opt -passes=correlated-propagation -S src.ll -o tgt.ll
clang src.ll -o src.out
clang tgt.ll -o tgt.out
```
Here are the complete [src.ll and tgt.ll](https://godbolt.org/z/G8s1cvWsd).
`lldb-commands.txt`:
```text
breakpoint set --file case.c --line 5
run
frame variable quotient
quit
```
Run LLDB on the binaries before and after `correlated-propagation`:
```sh
lldb src.out -s lldb-commands.txt
lldb tgt.out -s lldb-commands.txt
```
## Observed Behavior
Before `correlated-propagation`, LLDB reports the signed quotient:
```text
== src.out ==
(int) quotient = 1
```
After `correlated-propagation`, LLDB reports the constant used by the optimized computation:
```text
== tgt.out ==
(int) quotient = 0
```
The relevant IR before the pass is:
```llvm
%div = sdiv i32 %x, 42, !dbg !16
#dbg_value(i32 %div, !17, !DIExpression(), !15)
%0 = add i32 %x, 41, !dbg !18
%spec.select = icmp ult i32 %0, 83, !dbg !18
%cond = select i1 %spec.select, i32 %div, i32 24, !dbg !21
```
After the pass, the `sdiv` is removed and zero is used both by the select and by the debug record for `quotient`:
```llvm
#dbg_value(i32 0, !16, !DIExpression(), !15)
%0 = add i32 %x, 41, !dbg !17
%spec.select = icmp ult i32 %0, 83, !dbg !17
%cond = select i1 %spec.select, i32 0, i32 24, !dbg !20
```
Here, `!16` in the optimized IR is the source variable `quotient`:
```llvm
!16 = !DILocalVariable(name: "quotient", scope: !9, file: !1, line: 4, type: !12)
```
## Expected Behavior
The optimized debug information should not describe `quotient` with the constant `0` when it differs from the source-level signed quotient. At the breakpoint on line 5, LLDB should either report the original value `1` or report `quotient` as unavailable if the source value cannot be represented after eliminating the `sdiv`.
## Environment
```text
clang version 24.0.0git
llvm-project revision: f6ea145aa8e89631ae04f72df32580b20256d40c
LLVM version 24.0.0git
lldb version 24.0.0git
```
Contributor guide
Research direction
Reproduce the mismatch using case.c, the clang and opt commands, and the LLDB session described in the issue. Inspect the correlated-propagation pass and its handling of the quotient debug record in src.ll and tgt.ll. Done means optimized debug information preserves the source quotient when representable or marks it unavailable, without changing program behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100