llvm / llvm/llvm-project

[DebugInfo][CorrelatedValuePropagation] Replacing an `ashr` with `lshr` leaves a wrong debug value

Open
#218,366 1 comment 0 reactions 0 assignees View on GitHub
debuginfo llvm:transforms wrong-debug
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Description

`correlated-propagation` replaces an `ashr` with an `lshr` after proving that the shift result only affects program behavior when the input is non-negative. This transformation preserves the program result, but the `#dbg_value` for the source variable `shifted` remains attached to the rewritten instruction.

For a negative input, the source variable is the result of an arithmetic right shift, while the optimized debug information describes it using the result of a logical right shift. Consequently, LLDB prints `shifted` as `0x40000000` after the pass instead of the source-level value `0xc0000000`.

## Reproducer

`case.c`:

```c
#include

int ashr_to_lshr(int x, int y) {
int shifted = x >> y;
return x >= 0 ? shifted : 24;
}

int main(void) { return ashr_to_lshr(INT_MIN, 1) != 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' -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/48brWcMG3).

`lldb-commands.txt`:

```text
breakpoint set --file case.c --line 5
run
frame variable --format hex shifted
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 arithmetic-right-shift result:

```text
== src.out ==
(int) shifted = 0xc0000000
```

After `correlated-propagation`, LLDB reports the logical-right-shift result:

```text
== tgt.out ==
(int) shifted = 0x40000000
```

The relevant IR before the pass is:

```llvm
%shr = ashr i32 %x, %y, !dbg !17
#dbg_value(i32 %shr, !18, !DIExpression(), !15)
```

After the pass, `ashr` has become `lshr`, but the debug record still describes `shifted` directly with `%shr`:

```llvm
%shr = lshr i32 %x, %y, !dbg !17
#dbg_value(i32 %shr, !18, !DIExpression(), !15)
```

Here, `!18` is the source variable `shifted`:

```llvm
!18 = !DILocalVariable(name: "shifted", scope: !9, file: !1, line: 4, type: !12)
```

## Expected Behavior

The optimized debug information should not describe `shifted` with the logical-right-shift result when it differs from the source-level arithmetic-right-shift result. At the breakpoint on line 5, LLDB should either report the original value `0xc0000000` or report `shifted` 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 mismatch using case.c, the provided src.ll and tgt.ll pipeline, and lldb-commands.txt. Start by tracing the correlated-propagation pass where the ashr becomes lshr and its debug record remains attached; done means the optimized debug information reports the original value or marks shifted 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
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.