Skip to content

Commit b9f1e7b

Browse files
committed
[DebugInfo] Incorrect debug info record generated for loop counter.
Incorrect Debug Variable Range was calculated while "COMPUTING LIVE DEBUG VARIABLES" stage. Range for Debug Variable("i") computed according to current state of instructions inside of basic block. But Register Allocator creates new instructions which were not taken into account when Live Debug Variables computed. In the result DBG_VALUE instruction for the "i" variable was put after these newly inserted instructions. This is incorrect. Debug Value for the loop counter should be inserted before any loop instruction. Differential Revision: https://reviews.llvm.org/D62650 llvm-svn: 362750
1 parent 37bd9bd commit b9f1e7b

File tree

4 files changed

+176
-24
lines changed

4 files changed

+176
-24
lines changed

llvm/lib/CodeGen/LiveDebugVariables.cpp

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,6 @@ class UserValue {
167167
/// Map of slot indices where this value is live.
168168
LocMap locInts;
169169

170-
/// Set of interval start indexes that have been trimmed to the
171-
/// lexical scope.
172-
SmallSet<SlotIndex, 2> trimmedDefs;
173-
174170
/// Insert a DBG_VALUE into MBB at Idx for LocNo.
175171
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
176172
SlotIndex StopIdx, DbgValueLocation Loc, bool Spilled,
@@ -915,8 +911,7 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
915911
++I;
916912

917913
// If the interval also overlaps the start of the "next" (i.e.
918-
// current) range create a new interval for the remainder (which
919-
// may be further trimmed).
914+
// current) range create a new interval for the remainder
920915
if (RStart < IStop)
921916
I.insert(RStart, IStop, Loc);
922917
}
@@ -926,13 +921,6 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
926921
if (!I.valid())
927922
return;
928923

929-
if (I.start() < RStart) {
930-
// Interval start overlaps range - trim to the scope range.
931-
I.setStartUnchecked(RStart);
932-
// Remember that this interval was trimmed.
933-
trimmedDefs.insert(RStart);
934-
}
935-
936924
// The end of a lexical scope range is the last instruction in the
937925
// range. To convert to an interval we need the index of the
938926
// instruction after it.
@@ -1362,12 +1350,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
13621350
bool Spilled = SpillIt != SpillOffsets.end();
13631351
unsigned SpillOffset = Spilled ? SpillIt->second : 0;
13641352

1365-
// If the interval start was trimmed to the lexical scope insert the
1366-
// DBG_VALUE at the previous index (otherwise it appears after the
1367-
// first instruction in the range).
1368-
if (trimmedDefs.count(Start))
1369-
Start = Start.getPrevIndex();
1370-
13711353
LLVM_DEBUG(dbgs() << "\t[" << Start << ';' << Stop << "):" << Loc.locNo());
13721354
MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start)->getIterator();
13731355
SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
; RUN: llc -O3 -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -print-after virtregrewriter < %s >%t 2>&1 && FileCheck <%t %s
2+
3+
; This test checks that DBG_VALUE instruction placed correctly.
4+
; Specifically: if Register Allocator inserts additional instructions
5+
; in the beginning of basic block then it should not break placement
6+
; of DBG_VALUE for loop index variable. That DBG_VALUE instruction
7+
; for "i" variable should be placed before any real loop instruction.
8+
; https://reviews.llvm.org/D62650
9+
10+
; Created from the following C source:
11+
12+
; cat test_debug_val.cpp
13+
;
14+
; void func(int, ...);
15+
;
16+
; int array[0x100];
17+
;
18+
; int main( int argc, char **argv )
19+
; {
20+
; int var = 56;
21+
;
22+
; int a1 = array[1]; int a2 = array[2]; int a3 = array[3]; int a4 = array[4];
23+
; int a5 = array[5]; int a6 = array[6]; int a7 = array[7]; int a8 = array[8];
24+
; int a9 = array[9]; int a10 = array[10];
25+
;
26+
; for( int i = 0; i < 0x100; i++ ) {
27+
;
28+
; array[i] = var;
29+
;
30+
; func(0, i, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 );
31+
; }
32+
;
33+
; return 0;
34+
; }
35+
;
36+
;
37+
; clang -O3 -g -c --target=aarch64-unknown-linux -std=gnu++14 test_debug_val.cpp -emit-llvm -S -o -
38+
39+
40+
; CHECK: bb.2.for.body
41+
; CHECK-NEXT: predecessors
42+
; CHECK-NEXT: successors
43+
; CHECK-NEXT: liveins
44+
; CHECK-NOT: MOV
45+
; CHECK: DBG_VALUE $[[REG:[xw][0-9]+]], $noreg, !"i"
46+
; CHECK: MOV
47+
48+
; ModuleID = 'test_debug_val.cpp'
49+
source_filename = "test_debug_val.cpp"
50+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
51+
target triple = "aarch64-unknown-linux"
52+
53+
@array = dso_local local_unnamed_addr global [256 x i32] zeroinitializer, align 4, !dbg !0
54+
55+
; Function Attrs: norecurse
56+
define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 !dbg !14 {
57+
entry:
58+
call void @llvm.dbg.value(metadata i32 %argc, metadata !21, metadata !DIExpression()), !dbg !36
59+
call void @llvm.dbg.value(metadata i8** %argv, metadata !22, metadata !DIExpression()), !dbg !36
60+
call void @llvm.dbg.value(metadata i32 56, metadata !23, metadata !DIExpression()), !dbg !36
61+
%0 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 1), align 4, !dbg !37
62+
call void @llvm.dbg.value(metadata i32 %0, metadata !24, metadata !DIExpression()), !dbg !36
63+
%1 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 2), align 4, !dbg !42
64+
call void @llvm.dbg.value(metadata i32 %1, metadata !25, metadata !DIExpression()), !dbg !36
65+
%2 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 3), align 4, !dbg !43
66+
call void @llvm.dbg.value(metadata i32 %2, metadata !26, metadata !DIExpression()), !dbg !36
67+
%3 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 4), align 4, !dbg !44
68+
call void @llvm.dbg.value(metadata i32 %3, metadata !27, metadata !DIExpression()), !dbg !36
69+
%4 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 5), align 4, !dbg !45
70+
call void @llvm.dbg.value(metadata i32 %4, metadata !28, metadata !DIExpression()), !dbg !36
71+
%5 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 6), align 4, !dbg !46
72+
call void @llvm.dbg.value(metadata i32 %5, metadata !29, metadata !DIExpression()), !dbg !36
73+
%6 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 7), align 4, !dbg !47
74+
call void @llvm.dbg.value(metadata i32 %6, metadata !30, metadata !DIExpression()), !dbg !36
75+
%7 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 8), align 4, !dbg !48
76+
call void @llvm.dbg.value(metadata i32 %7, metadata !31, metadata !DIExpression()), !dbg !36
77+
%8 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 9), align 4, !dbg !49
78+
call void @llvm.dbg.value(metadata i32 %8, metadata !32, metadata !DIExpression()), !dbg !36
79+
%9 = load i32, i32* getelementptr inbounds ([256 x i32], [256 x i32]* @array, i64 0, i64 10), align 4, !dbg !50
80+
call void @llvm.dbg.value(metadata i32 %9, metadata !33, metadata !DIExpression()), !dbg !36
81+
call void @llvm.dbg.value(metadata i32 0, metadata !34, metadata !DIExpression()), !dbg !51
82+
br label %for.body, !dbg !52
83+
84+
for.cond.cleanup: ; preds = %for.body
85+
ret i32 0, !dbg !53
86+
87+
for.body: ; preds = %for.body, %entry
88+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
89+
call void @llvm.dbg.value(metadata i64 %indvars.iv, metadata !34, metadata !DIExpression()), !dbg !51
90+
%arrayidx = getelementptr inbounds [256 x i32], [256 x i32]* @array, i64 0, i64 %indvars.iv, !dbg !54
91+
store i32 56, i32* %arrayidx, align 4, !dbg !57
92+
%10 = trunc i64 %indvars.iv to i32, !dbg !58
93+
tail call void (i32, ...) @_Z4funciz(i32 0, i32 %10, i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9), !dbg !58
94+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !59
95+
call void @llvm.dbg.value(metadata i32 undef, metadata !34, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !51
96+
%exitcond = icmp eq i64 %indvars.iv.next, 256, !dbg !60
97+
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !52, !llvm.loop !61
98+
}
99+
100+
declare dso_local void @_Z4funciz(i32, ...) local_unnamed_addr #1
101+
102+
; Function Attrs: nounwind readnone speculatable
103+
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
104+
105+
attributes #0 = { nounwind uwtable }
106+
attributes #1 = { nounwind uwtable }
107+
attributes #2 = { nounwind readnone speculatable }
108+
109+
!llvm.dbg.cu = !{!2}
110+
!llvm.module.flags = !{!10, !11, !12}
111+
!llvm.ident = !{!13}
112+
113+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
114+
!1 = distinct !DIGlobalVariable(name: "array", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
115+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
116+
!3 = !DIFile(filename: "test_debug_val.cpp", directory: "")
117+
!4 = !{}
118+
!5 = !{!0}
119+
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 8192, elements: !8)
120+
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
121+
!8 = !{!9}
122+
!9 = !DISubrange(count: 256)
123+
!10 = !{i32 2, !"Dwarf Version", i32 4}
124+
!11 = !{i32 2, !"Debug Info Version", i32 3}
125+
!12 = !{i32 1, !"wchar_size", i32 4}
126+
!13 = !{!"clang version 9.0.0 "}
127+
!14 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 6, type: !15, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !20)
128+
!15 = !DISubroutineType(types: !16)
129+
!16 = !{!7, !7, !17}
130+
!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
131+
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
132+
!19 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
133+
!20 = !{!21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34}
134+
!21 = !DILocalVariable(name: "argc", arg: 1, scope: !14, file: !3, line: 6, type: !7)
135+
!22 = !DILocalVariable(name: "argv", arg: 2, scope: !14, file: !3, line: 6, type: !17)
136+
!23 = !DILocalVariable(name: "var", scope: !14, file: !3, line: 8, type: !7)
137+
!24 = !DILocalVariable(name: "a1", scope: !14, file: !3, line: 10, type: !7)
138+
!25 = !DILocalVariable(name: "a2", scope: !14, file: !3, line: 10, type: !7)
139+
!26 = !DILocalVariable(name: "a3", scope: !14, file: !3, line: 10, type: !7)
140+
!27 = !DILocalVariable(name: "a4", scope: !14, file: !3, line: 10, type: !7)
141+
!28 = !DILocalVariable(name: "a5", scope: !14, file: !3, line: 11, type: !7)
142+
!29 = !DILocalVariable(name: "a6", scope: !14, file: !3, line: 11, type: !7)
143+
!30 = !DILocalVariable(name: "a7", scope: !14, file: !3, line: 11, type: !7)
144+
!31 = !DILocalVariable(name: "a8", scope: !14, file: !3, line: 11, type: !7)
145+
!32 = !DILocalVariable(name: "a9", scope: !14, file: !3, line: 12, type: !7)
146+
!33 = !DILocalVariable(name: "a10", scope: !14, file: !3, line: 12, type: !7)
147+
!34 = !DILocalVariable(name: "i", scope: !35, file: !3, line: 14, type: !7)
148+
!35 = distinct !DILexicalBlock(scope: !14, file: !3, line: 14, column: 4)
149+
!36 = !DILocation(line: 0, scope: !14)
150+
!37 = !DILocation(line: 10, column: 13, scope: !14)
151+
!42 = !DILocation(line: 10, column: 32, scope: !14)
152+
!43 = !DILocation(line: 10, column: 51, scope: !14)
153+
!44 = !DILocation(line: 10, column: 70, scope: !14)
154+
!45 = !DILocation(line: 11, column: 13, scope: !14)
155+
!46 = !DILocation(line: 11, column: 32, scope: !14)
156+
!47 = !DILocation(line: 11, column: 51, scope: !14)
157+
!48 = !DILocation(line: 11, column: 70, scope: !14)
158+
!49 = !DILocation(line: 12, column: 13, scope: !14)
159+
!50 = !DILocation(line: 12, column: 33, scope: !14)
160+
!51 = !DILocation(line: 0, scope: !35)
161+
!52 = !DILocation(line: 14, column: 4, scope: !35)
162+
!53 = !DILocation(line: 21, column: 4, scope: !14)
163+
!54 = !DILocation(line: 16, column: 8, scope: !55)
164+
!55 = distinct !DILexicalBlock(scope: !56, file: !3, line: 14, column: 37)
165+
!56 = distinct !DILexicalBlock(scope: !35, file: !3, line: 14, column: 4)
166+
!57 = !DILocation(line: 16, column: 17, scope: !55)
167+
!58 = !DILocation(line: 18, column: 8, scope: !55)
168+
!59 = !DILocation(line: 14, column: 32, scope: !56)
169+
!60 = !DILocation(line: 14, column: 22, scope: !56)
170+
!61 = distinct !{!61, !52, !62}
171+
!62 = !DILocation(line: 19, column: 4, scope: !35)

llvm/test/DebugInfo/X86/dbg-addr-dse.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,12 @@ entry:
4646
}
4747

4848
; ASM-LABEL: f: # @f
49-
; ASM: movl %ecx, [[OFF_X:[0-9]+]](%rsp)
50-
; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [$rsp+0]
49+
; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X:[0-9]+]]] [$rsp+0]
50+
; ASM: movl %ecx, [[OFF_X]](%rsp)
5151
; ASM: callq escape
5252
; ASM: #DEBUG_VALUE: f:x <- 1
5353
; ASM: movl $1, global(%rip)
54-
; FIXME: Needs a fix to LiveDebugVariables
55-
; ASMX: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [$rsp+0]
54+
; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [$rsp+0]
5655
; ASM: movl $2, [[OFF_X]](%rsp)
5756
; ASM: callq escape
5857
; ASM: retq

llvm/test/DebugInfo/X86/live-debug-variables.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
; CHECK: .debug_loc contents:
2626
; CHECK-NEXT: 0x00000000:
2727
; We currently emit an entry for the function prologue, too, which could be optimized away.
28-
; CHECK: [0x0000000000000018, 0x0000000000000072): DW_OP_reg3 RBX
28+
; CHECK: [0x0000000000000010, 0x0000000000000072): DW_OP_reg3 RBX
2929
; We should only have one entry inside the function.
3030
; CHECK-NOT: :
3131

0 commit comments

Comments
 (0)