Skip to content

Commit 83ebef5

Browse files
author
Keith Walker
committedSep 27, 2016
Propagate DBG_VALUE entries when there are unvisited predecessors
Variables are sometimes missing their debug location information in blocks in which the variables should be available. This would occur when one or more predecessor blocks had not yet been visited by the routine which propagated the information from predecessor blocks. This is addressed by only considering predecessor blocks which have already been visited. The solution to this problem was suggested by Daniel Berlin on the LLVM developer mailing list. Differential Revision: https://reviews.llvm.org/D24927 llvm-svn: 282506
1 parent a42b3bc commit 83ebef5

File tree

2 files changed

+306
-10
lines changed

2 files changed

+306
-10
lines changed
 

‎llvm/lib/CodeGen/LiveDebugValues.cpp

+24-10
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ class LiveDebugValues : public MachineFunctionPass {
201201
VarLocInMBB &OutLocs, VarLocMap &VarLocIDs);
202202

203203
bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
204-
const VarLocMap &VarLocIDs);
204+
const VarLocMap &VarLocIDs,
205+
SmallPtrSet<const MachineBasicBlock *, 16> &Visited);
205206

206207
bool ExtendRanges(MachineFunction &MF);
207208

@@ -368,29 +369,41 @@ bool LiveDebugValues::transfer(MachineInstr &MI, OpenRangesSet &OpenRanges,
368369
/// inserting a new DBG_VALUE instruction at the start of the @MBB - if the same
369370
/// source variable in all the predecessors of @MBB reside in the same location.
370371
bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs,
371-
VarLocInMBB &InLocs, const VarLocMap &VarLocIDs) {
372+
VarLocInMBB &InLocs, const VarLocMap &VarLocIDs,
373+
SmallPtrSet<const MachineBasicBlock *, 16> &Visited) {
372374
DEBUG(dbgs() << "join MBB: " << MBB.getName() << "\n");
373375
bool Changed = false;
374376

375377
VarLocSet InLocsT; // Temporary incoming locations.
376378

377379
// For all predecessors of this MBB, find the set of VarLocs that
378380
// can be joined.
381+
int NumVisited = 0;
379382
for (auto p : MBB.predecessors()) {
383+
// Ignore unvisited predecessor blocks. As we are processing
384+
// the blocks in reverse post-order any unvisited block can
385+
// be considered to not remove any incoming values.
386+
if (!Visited.count(p))
387+
continue;
380388
auto OL = OutLocs.find(p);
381389
// Join is null in case of empty OutLocs from any of the pred.
382390
if (OL == OutLocs.end())
383391
return false;
384392

385-
// Just copy over the Out locs to incoming locs for the first predecessor.
386-
if (p == *MBB.pred_begin()) {
393+
// Just copy over the Out locs to incoming locs for the first visited
394+
// predecessor, and for all other predecessors join the Out locs.
395+
if (!NumVisited)
387396
InLocsT = OL->second;
388-
continue;
389-
}
390-
// Join with this predecessor.
391-
InLocsT &= OL->second;
397+
else
398+
InLocsT &= OL->second;
399+
NumVisited++;
392400
}
393401

402+
// As we are processing blocks in reverse post-order we
403+
// should have processed at least one predecessor, unless it
404+
// is the entry block which has no predecessor.
405+
assert((NumVisited || MBB.pred_empty()) &&
406+
"Should have processed at least one predecessor");
394407
if (InLocsT.empty())
395408
return false;
396409

@@ -463,6 +476,7 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
463476
// To solve it, we perform join() and transfer() using the two worklist method
464477
// until the ranges converge.
465478
// Ranges have converged when both worklists are empty.
479+
SmallPtrSet<const MachineBasicBlock *, 16> Visited;
466480
while (!Worklist.empty() || !Pending.empty()) {
467481
// We track what is on the pending worklist to avoid inserting the same
468482
// thing twice. We could avoid this with a custom priority queue, but this
@@ -472,8 +486,8 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
472486
while (!Worklist.empty()) {
473487
MachineBasicBlock *MBB = OrderToBB[Worklist.top()];
474488
Worklist.pop();
475-
MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs);
476-
489+
MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs, Visited);
490+
Visited.insert(MBB);
477491
if (MBBJoined) {
478492
MBBJoined = false;
479493
Changed = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
# RUN: llc -mtriple=arm-eabi -run-pass=livedebugvalues %s -o - | FileCheck %s
2+
#
3+
# Check that the debug information for variables are propagated into the correct blocks.
4+
#
5+
# Generated from the C source:
6+
#
7+
# int func2(int, int);
8+
# void func(int a) {
9+
# int b = func2(10, 11);
10+
# if (a) {
11+
# int c = func2(12, 13);
12+
# for(int i = 1; i < a; i++) {
13+
# func2(i, i+b);
14+
# }
15+
# func2(b,c);
16+
# }
17+
# func2(b,a);
18+
# }
19+
20+
# CHECK: [[VAR_A:![0-9]+]] = !DILocalVariable(name: "a",
21+
# CHECK: [[VAR_B:![0-9]+]] = !DILocalVariable(name: "b",
22+
# CHECK: [[VAR_C:![0-9]+]] = !DILocalVariable(name: "c",
23+
# CHECK: [[VAR_I:![0-9]+]] = !DILocalVariable(name: "i",
24+
25+
# CHECK: bb.0.entry
26+
# CHECK: DBG_VALUE debug-use %r0, debug-use _, [[VAR_A]]
27+
# CHECK: DBG_VALUE debug-use [[REG_A:%r[0-9]+]], debug-use _, [[VAR_A]]
28+
# CHECK: DBG_VALUE debug-use [[REG_B:%r[0-9]+]], debug-use _, [[VAR_B]]
29+
30+
# CHECK: bb.1.if.then
31+
# CHECK: DBG_VALUE debug-use [[REG_B]], debug-use _, [[VAR_B]]
32+
# CHECK: DBG_VALUE debug-use [[REG_A]], debug-use _, [[VAR_A]]
33+
# CHECK: DBG_VALUE debug-use [[REG_C:%r[0-9]+]], debug-use _, [[VAR_C]]
34+
# CHECK: DBG_VALUE 1, 0, [[VAR_I]]
35+
36+
# CHECK: bb.2.for.body
37+
# CHECK: DBG_VALUE debug-use [[REG_I:%r[0-9]+]], debug-use _, [[VAR_I]]
38+
# CHECK: DBG_VALUE debug-use [[REG_C]], debug-use _, [[VAR_C]]
39+
# CHECK: DBG_VALUE debug-use [[REG_B]], debug-use _, [[VAR_B]]
40+
# CHECK: DBG_VALUE debug-use [[REG_A]], debug-use _, [[VAR_A]]
41+
# CHECK: DBG_VALUE debug-use [[REG_I]], debug-use _, [[VAR_I]]
42+
43+
# CHECK: bb.3.for.cond
44+
# CHECK: DBG_VALUE debug-use [[REG_C]], debug-use _, [[VAR_C]]
45+
# CHECK: DBG_VALUE debug-use [[REG_B]], debug-use _, [[VAR_B]]
46+
# CHECK: DBG_VALUE debug-use [[REG_A]], debug-use _, [[VAR_A]]
47+
# CHECK: DBG_VALUE debug-use [[REG_I]], debug-use _, [[VAR_I]]
48+
49+
# CHECK: bb.4.for.cond.cleanup
50+
# CHECK: DBG_VALUE debug-use [[REG_I]], debug-use _, [[VAR_I]]
51+
# CHECK: DBG_VALUE debug-use [[REG_C]], debug-use _, [[VAR_C]]
52+
# CHECK: DBG_VALUE debug-use [[REG_B]], debug-use _, [[VAR_B]]
53+
# CHECK: DBG_VALUE debug-use [[REG_A]], debug-use _, [[VAR_A]]
54+
55+
# CHECK: bb.5.if.end
56+
# CHECK: DBG_VALUE debug-use [[REG_B]], debug-use _, [[VAR_B]]
57+
# CHECK: DBG_VALUE debug-use [[REG_A]], debug-use _, [[VAR_A]]
58+
--- |
59+
; ModuleID = '/data/kwalker/work/OpenSource-llvm/llvm/test/CodeGen/ARM/dbg-range-extension.ll'
60+
source_filename = "/data/kwalker/work/OpenSource-llvm/llvm/test/CodeGen/ARM/dbg-range-extension.ll"
61+
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
62+
target triple = "arm---eabi"
63+
64+
; Function Attrs: minsize nounwind optsize
65+
define void @func(i32 %a) local_unnamed_addr #0 !dbg !8 {
66+
entry:
67+
tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !13, metadata !20), !dbg !21
68+
%call = tail call i32 @func2(i32 10, i32 11) #0, !dbg !22
69+
tail call void @llvm.dbg.value(metadata i32 %call, i64 0, metadata !14, metadata !20), !dbg !23
70+
%tobool = icmp eq i32 %a, 0, !dbg !24
71+
br i1 %tobool, label %if.end, label %if.then, !dbg !25
72+
73+
if.then: ; preds = %entry
74+
%call1 = tail call i32 @func2(i32 12, i32 13) #0, !dbg !26
75+
tail call void @llvm.dbg.value(metadata i32 %call1, i64 0, metadata !15, metadata !20), !dbg !27
76+
tail call void @llvm.dbg.value(metadata i32 1, i64 0, metadata !18, metadata !20), !dbg !28
77+
br label %for.cond, !dbg !29
78+
79+
for.cond: ; preds = %for.body, %if.then
80+
%i.0 = phi i32 [ 1, %if.then ], [ %inc, %for.body ]
81+
tail call void @llvm.dbg.value(metadata i32 %i.0, i64 0, metadata !18, metadata !20), !dbg !28
82+
%cmp = icmp slt i32 %i.0, %a, !dbg !30
83+
br i1 %cmp, label %for.body, label %for.cond.cleanup, !dbg !33
84+
85+
for.cond.cleanup: ; preds = %for.cond
86+
%call3 = tail call i32 @func2(i32 %call, i32 %call1) #0, !dbg !34
87+
br label %if.end, !dbg !35
88+
89+
for.body: ; preds = %for.cond
90+
%0 = add i32 %call, %i.0, !dbg !36
91+
%call2 = tail call i32 @func2(i32 %i.0, i32 %0) #0, !dbg !36
92+
%inc = add nuw nsw i32 %i.0, 1, !dbg !38
93+
tail call void @llvm.dbg.value(metadata i32 %inc, i64 0, metadata !18, metadata !20), !dbg !28
94+
br label %for.cond, !dbg !40, !llvm.loop !41
95+
96+
if.end: ; preds = %for.cond.cleanup, %entry
97+
%call4 = tail call i32 @func2(i32 %call, i32 %a) #0, !dbg !43
98+
ret void, !dbg !44
99+
}
100+
101+
; Function Attrs: minsize optsize
102+
declare i32 @func2(i32, i32) local_unnamed_addr #1
103+
104+
; Function Attrs: nounwind readnone
105+
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
106+
107+
; Function Attrs: nounwind
108+
declare void @llvm.stackprotector(i8*, i8**) #3
109+
110+
attributes #0 = { minsize nounwind optsize }
111+
attributes #1 = { minsize optsize }
112+
attributes #2 = { nounwind readnone }
113+
attributes #3 = { nounwind }
114+
115+
!llvm.dbg.cu = !{!0}
116+
!llvm.module.flags = !{!3, !4, !5, !6}
117+
!llvm.ident = !{!7}
118+
119+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
120+
!1 = !DIFile(filename: "loop.c", directory: "/tmp")
121+
!2 = !{}
122+
!3 = !{i32 2, !"Dwarf Version", i32 4}
123+
!4 = !{i32 2, !"Debug Info Version", i32 3}
124+
!5 = !{i32 1, !"wchar_size", i32 4}
125+
!6 = !{i32 1, !"min_enum_size", i32 4}
126+
!7 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git b8f10df3679b36f51e1de7c4351b82d297825089) (http://llvm.org/git/llvm.git c2a5d16d1e3b8c49f5bbb1ff87a76ac4f88edb89)"}
127+
!8 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
128+
!9 = !DISubroutineType(types: !10)
129+
!10 = !{null, !11}
130+
!11 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
131+
!12 = !{!13, !14, !15, !18}
132+
!13 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 2, type: !11)
133+
!14 = !DILocalVariable(name: "b", scope: !8, file: !1, line: 3, type: !11)
134+
!15 = !DILocalVariable(name: "c", scope: !16, file: !1, line: 5, type: !11)
135+
!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 4, column: 9)
136+
!17 = distinct !DILexicalBlock(scope: !8, file: !1, line: 4, column: 6)
137+
!18 = !DILocalVariable(name: "i", scope: !19, file: !1, line: 6, type: !11)
138+
!19 = distinct !DILexicalBlock(scope: !16, file: !1, line: 6, column: 3)
139+
!20 = !DIExpression()
140+
!21 = !DILocation(line: 2, column: 15, scope: !8)
141+
!22 = !DILocation(line: 3, column: 17, scope: !8)
142+
!23 = !DILocation(line: 3, column: 13, scope: !8)
143+
!24 = !DILocation(line: 4, column: 6, scope: !17)
144+
!25 = !DILocation(line: 4, column: 6, scope: !8)
145+
!26 = !DILocation(line: 5, column: 11, scope: !16)
146+
!27 = !DILocation(line: 5, column: 7, scope: !16)
147+
!28 = !DILocation(line: 6, column: 11, scope: !19)
148+
!29 = !DILocation(line: 6, column: 7, scope: !19)
149+
!30 = !DILocation(line: 6, column: 20, scope: !31)
150+
!31 = !DILexicalBlockFile(scope: !32, file: !1, discriminator: 1)
151+
!32 = distinct !DILexicalBlock(scope: !19, file: !1, line: 6, column: 3)
152+
!33 = !DILocation(line: 6, column: 3, scope: !31)
153+
!34 = !DILocation(line: 9, column: 3, scope: !16)
154+
!35 = !DILocation(line: 10, column: 2, scope: !16)
155+
!36 = !DILocation(line: 7, column: 4, scope: !37)
156+
!37 = distinct !DILexicalBlock(scope: !32, file: !1, line: 6, column: 30)
157+
!38 = !DILocation(line: 6, column: 26, scope: !39)
158+
!39 = !DILexicalBlockFile(scope: !32, file: !1, discriminator: 3)
159+
!40 = !DILocation(line: 6, column: 3, scope: !39)
160+
!41 = distinct !{!41, !42}
161+
!42 = !DILocation(line: 6, column: 3, scope: !16)
162+
!43 = !DILocation(line: 11, column: 2, scope: !8)
163+
!44 = !DILocation(line: 12, column: 1, scope: !8)
164+
165+
...
166+
---
167+
name: func
168+
alignment: 2
169+
exposesReturnsTwice: false
170+
legalized: false
171+
regBankSelected: false
172+
selected: false
173+
tracksRegLiveness: false
174+
liveins:
175+
- { reg: '%r0' }
176+
calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13',
177+
'%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4',
178+
'%r5', '%r6', '%r7', '%r8', '%r9', '%r10', '%r11',
179+
'%s16', '%s17', '%s18', '%s19', '%s20', '%s21',
180+
'%s22', '%s23', '%s24', '%s25', '%s26', '%s27',
181+
'%s28', '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11',
182+
'%d10_d12', '%d11_d13', '%d12_d14', '%d13_d15',
183+
'%q4_q5', '%q5_q6', '%q6_q7', '%q4_q5_q6_q7', '%r4_r5',
184+
'%r6_r7', '%r8_r9', '%r10_r11', '%d8_d9_d10', '%d9_d10_d11',
185+
'%d10_d11_d12', '%d11_d12_d13', '%d12_d13_d14',
186+
'%d13_d14_d15', '%d8_d10_d12', '%d9_d11_d13', '%d10_d12_d14',
187+
'%d11_d13_d15', '%d8_d10_d12_d14', '%d9_d11_d13_d15',
188+
'%d9_d10', '%d11_d12', '%d13_d14', '%d9_d10_d11_d12',
189+
'%d11_d12_d13_d14' ]
190+
frameInfo:
191+
isFrameAddressTaken: false
192+
isReturnAddressTaken: false
193+
hasStackMap: false
194+
hasPatchPoint: false
195+
stackSize: 24
196+
offsetAdjustment: 0
197+
maxAlignment: 4
198+
adjustsStack: true
199+
hasCalls: true
200+
maxCallFrameSize: 0
201+
hasOpaqueSPAdjustment: false
202+
hasVAStart: false
203+
hasMustTailInVarArgFunc: false
204+
stack:
205+
- { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' }
206+
- { id: 1, type: spill-slot, offset: -8, size: 4, alignment: 4, callee-saved-register: '%r11' }
207+
- { id: 2, type: spill-slot, offset: -12, size: 4, alignment: 4, callee-saved-register: '%r7' }
208+
- { id: 3, type: spill-slot, offset: -16, size: 4, alignment: 4, callee-saved-register: '%r6' }
209+
- { id: 4, type: spill-slot, offset: -20, size: 4, alignment: 4, callee-saved-register: '%r5' }
210+
- { id: 5, type: spill-slot, offset: -24, size: 4, alignment: 4, callee-saved-register: '%r4' }
211+
body: |
212+
bb.0.entry:
213+
successors: %bb.5.if.end, %bb.1.if.then
214+
liveins: %r0, %r4, %r5, %r6, %r7, %r11, %lr
215+
216+
%sp = frame-setup STMDB_UPD %sp, 14, _, killed %r4, killed %r5, killed %r6, killed %r7, killed %r11, killed %lr
217+
frame-setup CFI_INSTRUCTION def_cfa_offset 24
218+
frame-setup CFI_INSTRUCTION offset %lr, -4
219+
frame-setup CFI_INSTRUCTION offset %r11, -8
220+
frame-setup CFI_INSTRUCTION offset %r7, -12
221+
frame-setup CFI_INSTRUCTION offset %r6, -16
222+
frame-setup CFI_INSTRUCTION offset %r5, -20
223+
frame-setup CFI_INSTRUCTION offset %r4, -24
224+
DBG_VALUE debug-use %r0, debug-use _, !13, !20, debug-location !21
225+
%r4 = MOVr killed %r0, 14, _, _
226+
DBG_VALUE debug-use %r4, debug-use _, !13, !20, debug-location !21
227+
%r0 = MOVi 10, 14, _, _, debug-location !22
228+
%r1 = MOVi 11, 14, _, _, debug-location !22
229+
BL @func2, csr_aapcs, implicit-def dead %lr, implicit %sp, implicit killed %r0, implicit killed %r1, implicit-def %sp, implicit-def %r0, debug-location !22
230+
%r5 = MOVr killed %r0, 14, _, _, debug-location !22
231+
DBG_VALUE debug-use %r5, debug-use _, !14, !20, debug-location !23
232+
CMPri %r4, 0, 14, _, implicit-def %cpsr, debug-location !25
233+
Bcc %bb.5.if.end, 0, killed %cpsr
234+
235+
bb.1.if.then:
236+
successors: %bb.3.for.cond
237+
liveins: %r4, %r5
238+
239+
%r0 = MOVi 12, 14, _, _, debug-location !26
240+
%r1 = MOVi 13, 14, _, _, debug-location !26
241+
BL @func2, csr_aapcs, implicit-def dead %lr, implicit %sp, implicit killed %r0, implicit killed %r1, implicit-def %sp, implicit-def %r0, debug-location !26
242+
%r6 = MOVr killed %r0, 14, _, _, debug-location !26
243+
DBG_VALUE debug-use %r6, debug-use _, !15, !20, debug-location !27
244+
%r7 = MOVi 1, 14, _, _
245+
DBG_VALUE 1, 0, !18, !20, debug-location !28
246+
B %bb.3.for.cond
247+
248+
bb.2.for.body:
249+
successors: %bb.3.for.cond
250+
liveins: %r4, %r5, %r6, %r7
251+
252+
%r1 = ADDrr %r5, %r7, 14, _, _, debug-location !36
253+
%r0 = MOVr %r7, 14, _, _, debug-location !36
254+
BL @func2, csr_aapcs, implicit-def dead %lr, implicit %sp, implicit killed %r0, implicit killed %r1, implicit-def %sp, implicit-def dead %r0, debug-location !36
255+
%r7 = ADDri killed %r7, 1, 14, _, _, debug-location !38
256+
DBG_VALUE debug-use %r7, debug-use _, !18, !20, debug-location !28
257+
258+
bb.3.for.cond:
259+
successors: %bb.2.for.body, %bb.4.for.cond.cleanup
260+
liveins: %r4, %r5, %r6, %r7
261+
262+
DBG_VALUE debug-use %r7, debug-use _, !18, !20, debug-location !28
263+
CMPrr %r7, %r4, 14, _, implicit-def %cpsr, debug-location !33
264+
Bcc %bb.2.for.body, 11, killed %cpsr, debug-location !33
265+
266+
bb.4.for.cond.cleanup:
267+
successors: %bb.5.if.end
268+
liveins: %r4, %r5, %r6
269+
270+
%r0 = MOVr %r5, 14, _, _, debug-location !34
271+
%r1 = MOVr killed %r6, 14, _, _, debug-location !34
272+
BL @func2, csr_aapcs, implicit-def dead %lr, implicit %sp, implicit killed %r0, implicit killed %r1, implicit-def %sp, implicit-def dead %r0, debug-location !34
273+
274+
bb.5.if.end:
275+
liveins: %r4, %r5
276+
277+
%r0 = MOVr killed %r5, 14, _, _, debug-location !43
278+
%r1 = MOVr killed %r4, 14, _, _, debug-location !43
279+
%sp = LDMIA_UPD %sp, 14, _, def %r4, def %r5, def %r6, def %r7, def %r11, def %lr, debug-location !43
280+
TAILJMPd @func2, implicit %sp, implicit %sp, implicit killed %r0, implicit killed %r1, debug-location !43
281+
282+
...

0 commit comments

Comments
 (0)
Please sign in to comment.