<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [DebugInfo@O2] LiveDebugVariables can drop DBG_VALUEs through misinterpreting fragments"
   href="https://bugs.llvm.org/show_bug.cgi?id=41992">41992</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[DebugInfo@O2] LiveDebugVariables can drop DBG_VALUEs through misinterpreting fragments
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Keywords</th>
          <td>wrong-debug
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Common Code Generator Code
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>jeremy.morse.llvm@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>aprantl@apple.com, chackz0x12@gmail.com, david.stenberg@ericsson.com, greg.bedwell@sony.com, llvm-bugs@lists.llvm.org, orlando.hyams@sony.com, paul.robinson@am.sony.com, stephen.tozer@sony.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>With LLVM/clang 361045, it seems LiveDebugVariables can drop DBG_VALUE
instructions in the presence of complex expressions, as demonstrated in the
code below, when fed into "llc -stop-after=virtregrewriter -o -". The code is
adapted from the dbg-addr-dse.ll test, and after virtregrewriter the third
DBG_VALUE instruction is not re-inserted, which makes an assignment disappear.

The cause seems to be this check [0] in LiveDebugVariables: it intends to
ensure that fragments are recorded as different "UserValue"s. However the fact
it's only comparing Expression pointers means that any complex expression at
all will be considered a different fragment of the variable. Thus the
DW_OP_deref's in the code below effectively make the dbg.value's refer to
different fragments, according to LiveDebugVariables.

In the example code, after calling collectDebugValues,
LiveDebugVariables::print represents the program state thus:

  !"x,3"   [32r;32d):0 [128r;128d):0 Loc0=%stack.0
  !"x,3"   [112r;112d):0 Loc0=1

Here the first and last DBG_VALUE insts are recorded in the first line as being
in location 0 (%stack.0) at slot indexes 32 and 128. The second line represents
the middle DBG_VALUE, as a different fragment, having location const-1 at slot
index 112. (The DIExpressions aren't printed).

After calling computeIntervals the LiveDebugVariables state becomes:

  !"x,3"   [48B;240B):0 Loc0=%stack.0
  !"x,3"   [112r;240B):0 Loc0=1

The first line coalesces its locations to the end of the block (240B) because
that "fragment" always appears to be in %stack.0. Then when virtregrewriter
re-inserts DBG_VALUEs, it doesn't see any reason to replace what was the third
DBG_VALUE in the original code: as far as it sees it, there are two different
fragments that get their locations defined once each, and that's it. Thus, the
third DBG_VALUE goes missing.

I anticipate LiveDebugVariables could be convinced to insert fresh DBG_VALUEs
where it shouldn't in a similar way. UserValue::extendDef can be convinced to
extend the lifetime of a fragment to a copy of a register location, if the
original register is killed. That would then lead to it inserting a fresh
DBG_VALUE, possibly terminating an earlier DBG_VALUE for the same (but
unrecognised) fragment.

(I was going to just submit a patch for this, but I think some non-trivial
datastructure changes are required, and it's not something I'm immediately
working on).

[0]
<a href="https://github.com/llvm/llvm-project/blob/e85bbf564de9adfe09d6b24b9861b28e2b78e9ad/llvm/lib/CodeGen/LiveDebugVariables.cpp#L207">https://github.com/llvm/llvm-project/blob/e85bbf564de9adfe09d6b24b9861b28e2b78e9ad/llvm/lib/CodeGen/LiveDebugVariables.cpp#L207</a>

--------8<--------
target triple = "x86_64-unknown-linux"

declare void @llvm.dbg.addr(metadata, metadata, metadata)
declare void @llvm.dbg.value(metadata, metadata, metadata)
declare void @escape(i32*)

@global = external global i32, align 4

define void @f(i32 %x) !dbg !8 {
entry:
  %x.addr = alloca i32, align 4
  store i32 %x, i32* %x.addr, align 4
  call void @llvm.dbg.value(metadata i32* %x.addr, metadata !13, metadata
!DIExpression(DW_OP_deref)), !dbg !18
  call void @escape(i32* %x.addr), !dbg !18
  call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata
!DIExpression()), !dbg !18
  store i32 1, i32* @global, align 4, !dbg !18
  call void @llvm.dbg.value(metadata i32* %x.addr, metadata !13, metadata
!DIExpression(DW_OP_deref)), !dbg !18
  store i32 2, i32* %x.addr, align 4, !dbg !18
  call void @escape(i32* %x.addr), !dbg !18
  ret void, !dbg !18
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!llvm.ident = !{!7}

!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang
version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug,
enums: !2)
!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!7 = !{!"clang version 6.0.0 "}
!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9,
isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped,
isOptimized: true, unit: !0, retainedNodes: !12)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type:
!11)
!18 = !DILocation(line: 3, column: 12, scope: !8)
-------->8--------</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>