Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -394,6 +394,7 @@ bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs, const VarLocMap &VarLocIDs, SmallPtrSet &Visited, + SmallPtrSet &SkippedVisited, SmallPtrSetImpl &ArtificialBlocks, VarLocInMBB &PendingInLocs); @@ -1039,6 +1040,7 @@ MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs, const VarLocMap &VarLocIDs, SmallPtrSet &Visited, + SmallPtrSet &SkippedVisited, SmallPtrSetImpl &ArtificialBlocks, VarLocInMBB &PendingInLocs) { LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n"); @@ -1050,12 +1052,16 @@ // can be joined. int NumVisited = 0; for (auto p : MBB.predecessors()) { - // Ignore unvisited predecessor blocks. As we are processing - // the blocks in reverse post-order any unvisited block can - // be considered to not remove any incoming values. + // Ignore backedges if we have not visited the predecessor yet. As the + // predecessor hasn't yet had locations propagated into it, most locations + // will not yet be valid. Instead, ignore the unvisited block for now and + // propagate the valid locations, adding this block to a list that needs + // revisiting. If a location guessed to be correct here is invalidated + // later, we will remove it when we revisit this block. if (!Visited.count(p)) { LLVM_DEBUG(dbgs() << " ignoring unvisited pred MBB: " << p->getNumber() << "\n"); + SkippedVisited.insert(&MBB); continue; } auto OL = OutLocs.find(p); @@ -1302,6 +1308,7 @@ // until the ranges converge. // Ranges have converged when both worklists are empty. SmallPtrSet Visited; + SmallPtrSet SkippedVisited; while (!Worklist.empty() || !Pending.empty()) { // We track what is on the pending worklist to avoid inserting the same // thing twice. We could avoid this with a custom priority queue, but this @@ -1311,7 +1318,7 @@ while (!Worklist.empty()) { MachineBasicBlock *MBB = OrderToBB[Worklist.top()]; Worklist.pop(); - MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs, Visited, + MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs, Visited, SkippedVisited, ArtificialBlocks, PendingInLocs); Visited.insert(MBB); if (MBBJoined) { @@ -1348,6 +1355,14 @@ } } } + + // Any blocks skipped because of an unvisited backedge will need to be + // reprocessed as well. + for (auto *MBB : SkippedVisited) + if (OnPending.insert(MBB).second) + Pending.push(BBToOrder[MBB]); + SkippedVisited.clear(); + Worklist.swap(Pending); // At this point, pending must be empty, since it was just the empty // worklist Index: test/DebugInfo/X86/DW_AT_location-reference.ll =================================================================== --- test/DebugInfo/X86/DW_AT_location-reference.ll +++ test/DebugInfo/X86/DW_AT_location-reference.ll @@ -32,10 +32,7 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000 -; Check that the location contains only 4 ranges - this verifies that the 4th -; and 5th ranges were successfully merged into a single range. -; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}): -; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}): +; Check that the location contains only 2 ranges. ; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}): ; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}): {{.*}}) ; CHECK-NEXT: DW_AT_name {{.*}} "x" Index: test/DebugInfo/X86/live-debug-values-remove-range.ll =================================================================== --- test/DebugInfo/X86/live-debug-values-remove-range.ll +++ test/DebugInfo/X86/live-debug-values-remove-range.ll @@ -5,12 +5,43 @@ ; 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" +; Second function @baz added with an even tighter loop -- this tests different +; code-paths through LiveDebugValues. Any blocks with an incoming backedge need +; reconsideration after the parent of the backedge has had its OutLocs +; initialized, even if OutLocs hasn't changed. ; +; Third function @quux tests that we don't delete too many variable locations. +; A variable that is live across the body of the loop should maintain its +; location across that loop, and not be invalidated. +; +; CHECK: ![[FOOVARNUM:[0-9]+]] = !DILocalVariable(name: "toast" +; CHECK: ![[BAZVARNUM:[0-9]+]] = !DILocalVariable(name: "crumpets" +; CHECK: ![[QUUXVARNUM:[0-9]+]] = !DILocalVariable(name: "teacake" +; +; foo tests +; CHECK-LABEL: bb.1.loop +; CHECK-NOT: DBG_VALUE +; CHECK-LABEL: CALL64pcrel32 @booler +; CHECK: DBG_VALUE 0, $noreg, ![[FOOVARNUM]] +; +; baz tests +; CHECK-LABEL: name: baz ; CHECK-LABEL: bb.1.loop ; CHECK-NOT: DBG_VALUE ; CHECK-LABEL: CALL64pcrel32 @booler -; CHECK: DBG_VALUE 0, $noreg, ![[VARNUM]] +; CHECK: DBG_VALUE 0, $noreg, ![[BAZVARNUM]] +; +; quux tests -- the variable arrives in $edi, should get a non-undef location +; before the loop, and its position re-stated in each block. +; CHECK-LABEL: name: quux +; CHECK: DBG_VALUE $edi, $noreg, ![[QUUXVARNUM]] +; CHECK: DBG_VALUE [[QUUXLOC:[a-zA-Z0-9$_]+]], $noreg, ![[QUUXVARNUM]] +; CHECK-LABEL: bb.1.loop +; CHECK: DBG_VALUE [[QUUXLOC]], $noreg, ![[QUUXVARNUM]] +; CHECK-NOT: DBG_VALUE $noreg +; CHECK-LABEL: bb.2.exit +; CHECK: DBG_VALUE [[QUUXLOC]], $noreg, ![[QUUXVARNUM]] +; CHECK-NOT: DBG_VALUE $noreg declare i1 @booler() declare void @escape(i32) @@ -33,6 +64,32 @@ ret i32 %bar } +define i32 @baz(i32 %bar) !dbg !104 { +entry: + call void @llvm.dbg.value(metadata i32 %bar, metadata !103, metadata !DIExpression()), !dbg !106 + br label %loop +loop: + call void @escape(i32 %bar) + %retval = call i1 @booler(), !dbg !106 + call void @llvm.dbg.value(metadata i32 0, metadata !103, metadata !DIExpression()), !dbg !106 + br i1 %retval, label %loop, label %exit +exit: + ret i32 %bar +} + +define i32 @quux(i32 %bar) !dbg !204 { +entry: + ; %bar will be placed in a nonvolatile or spill location for the loop, + ; before being returned later. + call void @llvm.dbg.value(metadata i32 %bar, metadata !203, metadata !DIExpression()), !dbg !206 + br label %loop +loop: + %retval = call i1 @booler(), !dbg !206 + br i1 %retval, label %loop, label %exit +exit: + ret i32 %bar +} + !llvm.module.flags = !{!0, !100} !llvm.dbg.cu = !{!1} @@ -47,3 +104,11 @@ !14 = !DISubroutineType(types: !15) !15 = !{!16} !16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!103 = !DILocalVariable(name: "crumpets", scope: !104, file: !2, line: 1, type: !16) +!104 = distinct !DISubprogram(name: "ribbit", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !113, type: !14, isDefinition: true) +!106 = !DILocation(line: 1, scope: !104) +!113 = !{!103} +!203 = !DILocalVariable(name: "teacake", scope: !204, file: !2, line: 1, type: !16) +!204 = distinct !DISubprogram(name: "toad", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !113, type: !14, isDefinition: true) +!206 = !DILocation(line: 1, scope: !204) +!213 = !{!203}