You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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:
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).
Extended Description
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]
llvm-project/llvm/lib/CodeGen/LiveDebugVariables.cpp
Line 207 in e85bbf5
--------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--------
The text was updated successfully, but these errors were encountered: