Skip to content

[DebugInfo][CorrelatedValuePropagation] Narrowing sdiv/srem can leave wrong debug values #218406

Description

@MrEven132

Description

correlated-propagation narrows sdiv i16 and srem i16 operations to i8 after proving that their results only affect program behavior when the dividend is strictly between -43 and 43. Values in that range fit in i8, so truncating the dividend, calculating the quotient or remainder in i8, and sign-extending the result back to i16 preserves the program result.

However, the #dbg_value records for the source variables are changed to describe the narrowed results for every input. For values outside the inferred range, truncating the dividend can change both the quotient and remainder even though the source variables can still be inspected. With x = 252, LLDB prints quotient as 0 instead of 6, and remainer as -4 instead of 0.

Reproducer

case.c:

#include <stdbool.h>

typedef signed _BitInt(16) i16;

i16 sdiv_narrow(i16 x) {
  i16 quotient = x / (i16)42;
  bool __attribute__((nodebug)) in_range = (x < (i16)43) && (x > (i16)-43);
  return in_range ? quotient : (i16)24;
}

i16 srem_narrow(i16 x) {
  i16 remainer = x % (i16)42;
  bool  in_range = (x < (i16)43) && (x > (i16)-43);
  return in_range ? remainer : (i16)24;
}

int main(void) {
  return sdiv_narrow(252) != 24 || srem_narrow(252) != 24;
}

Build pipeline:

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.

lldb-commands.txt:

breakpoint set --file case.c --line 7
breakpoint set --file case.c --line 14
run
frame variable quotient
continue
frame variable remainer
quit

Run LLDB on the binaries before and after correlated-propagation:

lldb src.out -s lldb-commands.txt
lldb tgt.out -s lldb-commands.txt

Observed Behavior

For sdiv, LLDB reports the source-level quotient before correlated-propagation:

== src.out ==
(i16) quotient = 6

After correlated-propagation, LLDB reports the result of the narrowed computation:

== tgt.out ==
(i16) quotient = 0

For srem, LLDB reports the source-level remainder before correlated-propagation:

== src.out ==
(i16) remainer = 0

After correlated-propagation, LLDB reports the result of the narrowed computation:

== tgt.out ==
(i16) remainer = -4

The relevant IR before the pass contains the original i16 operations and debug records:

%div = sdiv i16 %x, 42, !dbg !18
  #dbg_value(i16 %div, !19, !DIExpression(), !17)

%rem = srem i16 %x, 42, !dbg !26
  #dbg_value(i16 %rem, !27, !DIExpression(), !25)

After the pass, each dividend is truncated to i8, the operation is performed in i8, and the result is sign-extended back to i16. The debug records describe these narrowed results directly:

%div.lhs.trunc = trunc i16 %x to i8, !dbg !18
%div1 = sdiv i8 %div.lhs.trunc, 42, !dbg !18
%div.sext = sext i8 %div1 to i16, !dbg !18
  #dbg_value(i16 %div.sext, !19, !DIExpression(), !17)

%rem.lhs.trunc = trunc i16 %x to i8, !dbg !26
%rem1 = srem i8 %rem.lhs.trunc, 42, !dbg !26
%rem.sext = sext i8 %rem1 to i16, !dbg !26
  #dbg_value(i16 %rem.sext, !27, !DIExpression(), !25)

Here, !19 and !27 are the source variables quotient and remainer:

!19 = !DILocalVariable(name: "quotient", scope: !12, file: !1, line: 6, type: !3)
!27 = !DILocalVariable(name: "remainer", scope: !23, file: !1, line: 12, type: !3)

Expected Behavior

The optimized debug information should not describe source variables with narrowed sdiv or srem results when they differ from the source-level i16 operations. LLDB should either report the original values, quotient = 6 and remainer = 0, or report the variables as unavailable if their source values cannot be represented after narrowing.

Environment

clang version 24.0.0git
llvm-project revision: f6ea145aa8e89631ae04f72df32580b20256d40c
Target: x86_64-unknown-linux-gnu

LLVM version 24.0.0git
lldb version 24.0.0git
Linux x86_64

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions