[DebugInfo][CorrelatedValuePropagation] Replacing `sitofp` with `uitofp` leaves a wrong debug value
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Description
`correlated-propagation` replaces a `sitofp` with `uitofp nneg` after proving that the converted value only affects program behavior when the input is non-negative. This preserves the program result, but the `#dbg_value` for the source variable `converted` remains attached to the unsigned conversion result.
For a negative input, signed and unsigned integer-to-floating-point conversions produce different values. Consequently, LLDB prints `converted` as approximately `4.2949673E+9` after the pass instead of the source-level value `-1`.
## Reproducer
`case.c`:
```c
float sitofp_to_uitofp(int x) {
float converted = (float)x;
return x >= 0 ? converted : 0.0f;
}
int main(void) { return sitofp_to_uitofp(-1) != 0.0f; }
```
Build pipeline:
```sh
clang -g -O0 -march=x86-64-v4 -Xclang -disable-O0-optnone -fno-discard-value-names -S -emit-llvm case.c -o case.ll
opt -passes='mem2reg,simplifycfg' -S case.ll -o src.ll
opt -passes=correlated-propagation -S src.ll -o tgt.ll
clang src.ll -march=x86-64-v4 -o src.out
clang tgt.ll -march=x86-64-v4 -o tgt.out
```
Here are the complete [src.ll and tgt.ll](https://godbolt.org/z/r6TYrjYY6).
`lldb-commands.txt`:
```text
breakpoint set --file case.c --line 3
run
frame variable converted
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 integer-to-floating-point conversion:
```text
== src.out ==
(float) converted = -1
```
After `correlated-propagation`, LLDB reports the unsigned conversion result:
```text
== tgt.out ==
(float) converted = 4.2949673E+9
```
The relevant IR before the pass is:
```llvm
%conv = sitofp i32 %x to float, !dbg !18
#dbg_value(float %conv, !19, !DIExpression(), !17)
```
After the pass, `sitofp` has become `uitofp nneg`, but the debug record still describes `converted` directly with `%conv`:
```llvm
%conv = uitofp nneg i32 %x to float, !dbg !18
#dbg_value(float %conv, !19, !DIExpression(), !17)
```
Here, `!19` is the source variable `converted`:
```llvm
!19 = !DILocalVariable(name: "converted", scope: !11, file: !1, line: 2, type: !3)
```
## Expected Behavior
The optimized debug information should not describe `converted` with the unsigned conversion result when it differs from the source-level signed conversion. At the breakpoint on line 3, LLDB should either report the original value `-1` or report `converted` as unavailable if the source value cannot be represented after the transformation.
## 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 issue with case.c using the clang, opt, and LLDB commands provided, then compare the debug records in src.ll and tgt.ll around the correlated-propagation pass. Trace how the pass transforms sitofp and its #dbg_value; done means LLDB reports the signed source value or marks converted unavailable after the transformation.
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
- Mostly clear
- Newbie friendliness
- 45/100