[llvm-bugs] [Bug 39726] New: [DebugInfo at O2][Dexter] Pointer variable location can be dropped despite being live

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Nov 20 10:33:58 PST 2018


            Bug ID: 39726
           Summary: [DebugInfo at O2][Dexter] Pointer variable location can
                    be dropped despite being live
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: CONFIRMED
          Keywords: wrong-debug
          Severity: normal
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: jeremy.morse.llvm at gmail.com
                CC: carlos.alberto.enciso at gmail.com, chackz0x12 at gmail.com,
                    greg.bedwell at sony.com, llvm-bugs at lists.llvm.org,
                    paul.robinson at am.sony.com
            Blocks: 38754, 38768

Spinning this out of bug 38754, this bug is about an unfortunate dropping of a
dbg.value when it's located in the "correct" place. In the code at the bottom
of this bug, the "qux" variable in "main" can have its location dropped,
preventing the developer seeing anything useful in the function. I've been
using llvm/clang r346686 with options "-O2 -g". The problem described below
only happens if you disable CodeGenPrepare's placeDbgValues method (which I'm
trying to eliminate). Alternately you can replicate this behaviour with other
clangs by:

  clang++ test.cpp -O2 -g -mllvm -stop-after=codegenprepare -c -o out.mir
  [Edit out.mir moving dbg.value for 'qux' to occur after inlined 
   constructor completes, after the merged store to the 'fgasdf' field]
  llc -start-after=codegenprepare out.mir -o out.s
  clang++ out.s -o a.out

In plain clang from trunk, in the code below the dbg.value for 'qux' is moved
to immediately after the call to 'new': it's emitted as a DBG_VALUE in the
first BB, and its lifetime extended across the body of the whole function.

Without placeDbgValues, however, the dbg.value for 'qux' stays in its original
location after the constructor call, and due to some curious behaviours the SSA
register it's applied to is never used. The DBG_VALUE for qux is never emitted
because it appears a dead value if it's left in the "correct" location.

The reason why this happens is easy to explain (see below), there are sane
reasons why. This bug however is about the fact that the combined behaviours
leads to an (IMHO) unacceptable outcome, where a pointer variable of
significant interest to the developer (and which is in a live register the
~whole function) has debug info dropped.

Here's the IR for main (with correctly placed dbg.value) with comments where
I've omitted code:
  ; Call to allocate "qux"
  %3 = tail call i8* @_Znwm(i64 4) #7
  ; The constructor for class foo is inlined, including a conditional
  ; jump between BBs because of the if-condition, finishing with a write
  ; to fgasdf:
  %13 = bitcast i8* %3 to %class.foo*
  %14 = bitcast i8* %3 to i32*
  store i32 %12, i32* %14, align 4
  ; The constructor complete, we make the dbg.value call for "qux"
  call void @llvm.dbg.value(metadata i8* %3, metadata !28, [blah])
  ; The body for 'spoons' and the printf call are performed using SSA
  ; registers and no further loads/stores, finally:
  tail call void @_ZN3foo9loldeleteEPS_(%class.foo* nonnull %13)
  ret i32 0

The dbg.value is applied to an SSA variable of type "i8*", but everything else
after that instruction either doesn't touch the allocated object, or uses the
pointer SSA-reg that's been cast to "%class.foo*", i.e. %13. In combination
with the fact that the dbg.value is no longer in the basic block where %3 is
defined, SelectionDAG then drops the DBG_VALUE. This scenario is avoided if we
were to:
 * Not having a jump-forcing conditional in the constructor
 * Not inline anything
 * Call delete directly rather then calling a static method to delete
   (the delete operation appears to consume an i8*)

To summarise, if we leave the dbg.value for "qux" in the code below in the
correct location (after the constructor), then by accident we end up dropping
it. It seems obvious that there should be a way around this, either by
something looking further through casts, or the dbg.value being applied to the
"correctly" (TM) typed SSA-reg-pointer. I think this might be a fairly general
problem though, of the form:
 * Lots of code inlined into a function
 * All the inlined code GEPs or casts pointers to various elements of
   data structures
 * After a certain point in the function, all the base pointers to the
   relevant data structures appear to go out of liveness, not because 
   they're dead but because subsequent code refers to the memory with a
   different type.

(This is important because placeDbgValues must die IMHO, so this bug will
eventually present to an end user). The code is below; I've scattered noinline
to emulate function calls that don't get inlined while keeping it

#include <stdio.h>

__attribute__((noinline)) int rand() {
  volatile int foo = 4;
  return foo;

class foo {
  int fgasdf;
  foo(int i) {
    if (rand() == 4)
      fgasdf = rand() * i;
      fgasdf = rand() / i;

  int spoons(int u) {
    return fgasdf * u + rand();

  __attribute__((noinline)) static void loldelete(foo *go) {
    delete go;

int main(int argc, char **argv) {
  foo *qux = new foo(argc);
  int bees = qux->spoons(argc);
  printf("%d\n", bees);
  return 0;

Referenced Bugs:

[Bug 38754] [DebugInfo at O2][Dexter] Illegal value appears in variable when
conditional blocks folded
[Bug 38768] [meta][DebugInfo] Umbrella bug for poor debug experiences
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181120/9c151906/attachment-0001.html>

More information about the llvm-bugs mailing list