llvm / llvm/llvm-project

[DebugInfo][CorrelatedValuePropagation] Replacing `sitofp` with `uitofp` leaves a wrong debug value

Open
#218,627 1 comment 0 reactions 0 assignees View on GitHub
debuginfo llvm:transforms
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.