From 81f9699a8923219ba02c43f4eab74af85b393c8c Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Fri, 23 Aug 2019 16:33:42 +0000 Subject: [PATCH] [DebugInfo] Remove invalidated locations during LiveDebugValues LiveDebugValues gives variable locations to blocks, but it should also take away. There are various circumstances where a variable location is known until a loop backedge with a different location is detected. In those circumstances, where there's no agreement on the variable location, it should be undef / removed, otherwise we end up picking a location that's valid on some loop iterations but not others. However, LiveDebugValues doesn't currently do this, see the new testcase attached. Without this patch, the location of !3 is assumed to be %bar through the loop. Once it's added to the In-Locations list, it's never removed, even though the later dbg.value(0... of !3 makes the location un-knowable. This patch checks during block-location-joining to see whether any previously-present locations have been removed in a predecessor. If they have, the live-ins have changed, and the block needs reprocessing. Similarly, in transferTerminator, assign rather than |= the Out-Locations after processing a block, as we may have deleted some previously valid locations. This will mean that LiveDebugValues performs more propagation -- but that's necessary for it being correct. Differential Revision: https://reviews.llvm.org/D66599 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369778 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/LiveDebugValues.cpp | 18 +++++-- test/DebugInfo/COFF/pieces.ll | 1 - test/DebugInfo/X86/fission-ranges.ll | 2 +- .../X86/live-debug-values-remove-range.ll | 49 +++++++++++++++++++ 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 test/DebugInfo/X86/live-debug-values-remove-range.ll diff --git a/lib/CodeGen/LiveDebugValues.cpp b/lib/CodeGen/LiveDebugValues.cpp index 033394fb0f5..1ddcceabe20 100644 --- a/lib/CodeGen/LiveDebugValues.cpp +++ b/lib/CodeGen/LiveDebugValues.cpp @@ -77,6 +77,7 @@ using namespace llvm; #define DEBUG_TYPE "livedebugvalues" STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted"); +STATISTIC(NumRemoved, "Number of DBG_VALUE instructions removed"); // If @MI is a DBG_VALUE with debug value described by a defined // register, returns the number of this register. In the other case, returns 0. @@ -942,7 +943,7 @@ bool LiveDebugValues::transferTerminator(MachineBasicBlock *CurMBB, VarLocIDs[ID].dump(); }); VarLocSet &VLS = OutLocs[CurMBB]; - Changed = VLS |= OpenRanges.getVarLocs(); + Changed = VLS != OpenRanges.getVarLocs(); // New OutLocs set may be different due to spill, restore or register // copy instruction processing. if (Changed) @@ -1101,8 +1102,6 @@ bool LiveDebugValues::join( // is the entry block which has no predecessor. assert((NumVisited || MBB.pred_empty()) && "Should have processed at least one predecessor"); - if (InLocsT.empty()) - return false; VarLocSet &ILS = InLocs[&MBB]; VarLocSet &Pending = PendingInLocs[&MBB]; @@ -1118,6 +1117,19 @@ bool LiveDebugValues::join( ++NumInserted; Changed = true; } + + // We may have lost locations by learning about a predecessor that either + // loses or moves a variable. Find any locations in ILS that are not in the + // new in-locations, and delete those. + VarLocSet Removed = ILS; + Removed.intersectWithComplement(InLocsT); + for (auto ID : Removed) { + Pending.reset(ID); + ILS.reset(ID); + ++NumRemoved; + Changed = true; + } + return Changed; } diff --git a/test/DebugInfo/COFF/pieces.ll b/test/DebugInfo/COFF/pieces.ll index f864931a290..2fcc5b70317 100644 --- a/test/DebugInfo/COFF/pieces.ll +++ b/test/DebugInfo/COFF/pieces.ll @@ -43,7 +43,6 @@ ; ASM: [[oy_ox_start:\.Ltmp[0-9]+]]: ; ASM: .p2align 4, 0x90 ; ASM: .LBB0_3: # %for.body -; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] 0 ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi ; ASM: .cv_loc 0 1 13 11 # t.c:13:11 diff --git a/test/DebugInfo/X86/fission-ranges.ll b/test/DebugInfo/X86/fission-ranges.ll index 106834d9284..c2b355b994c 100644 --- a/test/DebugInfo/X86/fission-ranges.ll +++ b/test/DebugInfo/X86/fission-ranges.ll @@ -45,7 +45,7 @@ ; if they've changed due to a bugfix, change in register allocation, etc. ; CHECK: [[A]]: -; CHECK-NEXT: Addr idx 2 (w/ length 169): DW_OP_consts +0, DW_OP_stack_value +; CHECK-NEXT: Addr idx 2 (w/ length 15): DW_OP_consts +0, DW_OP_stack_value ; CHECK-NEXT: Addr idx 3 (w/ length 15): DW_OP_reg0 RAX ; CHECK-NEXT: Addr idx 4 (w/ length 18): DW_OP_breg7 RSP-8 ; CHECK: [[E]]: diff --git a/test/DebugInfo/X86/live-debug-values-remove-range.ll b/test/DebugInfo/X86/live-debug-values-remove-range.ll new file mode 100644 index 00000000000..3d5219e74c1 --- /dev/null +++ b/test/DebugInfo/X86/live-debug-values-remove-range.ll @@ -0,0 +1,49 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown %s -o - -stop-after=livedebugvalues | FileCheck %s +; +; In the simple loop below, the location of the variable "toast" is %bar in +; the entry block, then set to constant zero at the end of the loop. We cannot +; know the location of "toast" at the start of the %loop block. Test that no +; location is given until after the call to @booler. +; +; CHECK: ![[VARNUM:[0-9]+]] = !DILocalVariable(name: "toast" +; +; CHECK-LABEL: bb.1.loop +; CHECK-NOT: DBG_VALUE +; CHECK-LABEL: CALL64pcrel32 @booler +; CHECK: DBG_VALUE 0, $noreg, ![[VARNUM]] + +declare i1 @booler() +declare void @escape(i32) +declare void @llvm.dbg.value(metadata, metadata, metadata) +@glob = global i32 0 + +define i32 @foo(i32 %bar) !dbg !4 { +entry: + call void @llvm.dbg.value(metadata i32 %bar, metadata !3, metadata !DIExpression()), !dbg !6 + br label %loop +loop: + call void @escape(i32 %bar) + %retval = call i1 @booler(), !dbg !6 + call void @llvm.dbg.value(metadata i32 0, metadata !3, metadata !DIExpression()), !dbg !6 + br i1 %retval, label %loop2, label %exit +loop2: + store i32 %bar, i32 *@glob + br label %loop +exit: + ret i32 %bar +} + +!llvm.module.flags = !{!0, !100} +!llvm.dbg.cu = !{!1} + +!100 = !{i32 2, !"Dwarf Version", i32 4} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!2 = !DIFile(filename: "bees.cpp", directory: ".") +!3 = !DILocalVariable(name: "toast", scope: !4, file: !2, line: 1, type: !16) +!4 = distinct !DISubprogram(name: "nope", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true) +!6 = !DILocation(line: 1, scope: !4) +!13 = !{!3} +!14 = !DISubroutineType(types: !15) +!15 = !{!16} +!16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) -- 2.40.0