Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DebugInfo@O2] LiveDebugVariables can drop DBG_VALUEs through misinterpreting fragments #41337

Closed
jmorse opened this issue May 23, 2019 · 4 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla llvm:codegen wrong-debug

Comments

@jmorse
Copy link
Member

jmorse commented May 23, 2019

Bugzilla Link 41992
Resolution FIXED
Resolved on Feb 13, 2020 07:33
Version trunk
OS Linux
Blocks #38116
CC @adrian-prantl,@dstenb,@gregbedwell,@jdm,@OCHyams,@pogo59,@Melamoto
Fixed by commit(s) 1e40799

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]

// FIXME: The fragment should be part of the equivalence class, but not

--------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--------

@jmorse
Copy link
Member Author

jmorse commented May 23, 2019

assigned to @OCHyams

@OCHyams
Copy link
Contributor

OCHyams commented Nov 12, 2019

WIP patch here https://reviews.llvm.org/D70121

@OCHyams
Copy link
Contributor

OCHyams commented Nov 15, 2019

Adding this to the DebugInfo@O2 umbrella bug 38768.

@OCHyams
Copy link
Contributor

OCHyams commented Feb 13, 2020

Fixed with D74053 (1e40799).

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm:codegen wrong-debug
Projects
None yet
Development

No branches or pull requests

2 participants