llvm / llvm/llvm-project

[DebugInfo][CorrelatedValuePropagation] Replacing `llvm.smin`/`llvm.smax` with `llvm.umin`/`llvm.umax` counterparts can leave wrong debug values

Open
#218,626 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` can replace `llvm.smin`/`llvm.smax` with `llvm.umin`/`llvm.umax` after proving that the result only affects program behavior when the operands satisfy the required non-negative range. This preserves the program result, but a `#dbg_value` describing the signed result can remain attached to the unsigned operation result.

This reproducer demonstrates the `llvm.smin` to `llvm.umin` case. For a negative input, signed and unsigned minimum operations produce different values. Consequently, LLDB prints `minimum` as `42` after the pass instead of the source-level value `-1`. The analogous `llvm.smax` to `llvm.umax` transformation has the same debug-info problem when the signed and unsigned maximum results differ outside the range required for program semantics.

## Reproducer

`case.c`:

```c
int smin_to_umin(int x) {
int minimum = __builtin_elementwise_min(x, 42);
return x >= 0 ? minimum : 24;
}

int main(void) { return smin_to_umin(-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/b94fEsEYx).

`lldb-commands.txt`:

```text
breakpoint set --file case.c --line 3
run
frame variable minimum
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 minimum:

```text
== src.out ==
(int) minimum = -1
```

After `correlated-propagation`, LLDB reports the unsigned minimum:

```text
== tgt.out ==
(int) minimum = 42
```

The relevant IR before the pass is:

```llvm
%elt.min = call i32 @llvm.smin.i32(i32 %x, i32 42), !dbg !16
#dbg_value(i32 %elt.min, !17, !DIExpression(), !15)
```

After the pass, `llvm.smin` has become `llvm.umin`, but the debug record still describes `minimum` directly with its result:

```llvm
%0 = call i32 @llvm.umin.i32(i32 %x, i32 42), !dbg !16
#dbg_value(i32 %0, !17, !DIExpression(), !15)
```

Here, `!17` is the source variable `minimum`:

```llvm
!17 = !DILocalVariable(name: "minimum", scope: !9, file: !1, line: 2, type: !12)
```

## Expected Behavior

The optimized debug information should not describe `minimum` with the unsigned minimum result when it differs from the source-level signed minimum. At the breakpoint on line 3, LLDB should either report the original value `-1` or report `minimum` as unavailable if the source value cannot be represented after the transformation. The same requirement applies when `llvm.smax` is replaced with `llvm.umax`.

## 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 listed clang, opt, and LLDB commands, then inspect the correlated-propagation implementation and its handling of debug records during llvm.smin/llvm.smax to llvm.umin/llvm.umax replacements. Confirm completion by ensuring LLDB reports the original signed value or marks minimum unavailable for both minimum and maximum cases.

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
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.