1 # RUN: llc -O1 -start-after=livedebugvalues -o - %s | FileCheck %s
3 # Reproducer based on the following C file:
5 # int global1, global2, global3;
7 # extern void ext1(int);
8 # extern void ext2(int, int);
9 # extern void ext3(int, int, int);
12 # int local[3] = {global1, 123, 456};
13 # ext2(local[0], local[1]);
18 # int local[3] = {global1, global2, global3};
19 # ext3(local[0], local[1], local[2]);
23 # Compiled using -O1 -g.
26 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
27 target triple = "x86_64-unknown-linux-gnu"
29 @global1 = common global i32 0, align 4
30 @global2 = common global i32 0, align 4
31 @global3 = common global i32 0, align 4
33 ; Function Attrs: nounwind uwtable
34 define i32 @test1() #0 !dbg !8 {
36 %0 = load i32, i32* @global1, align 4, !dbg !16
37 call void @llvm.dbg.value(metadata i32 %0, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !16
38 call void @llvm.dbg.value(metadata i32 123, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32)), !dbg !16
39 call void @llvm.dbg.value(metadata i32 456, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32)), !dbg !16
40 tail call void @ext2(i32 %0, i32 123), !dbg !16
44 declare void @ext2(i32, i32)
46 ; Function Attrs: nounwind uwtable
47 define i32 @test2() #0 !dbg !18 {
49 %0 = load i32, i32* @global1, align 4, !dbg !20
50 call void @llvm.dbg.value(metadata i32 %0, metadata !19, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !20
51 %1 = load i32, i32* @global2, align 4, !dbg !20
52 call void @llvm.dbg.value(metadata i32 %1, metadata !19, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32)), !dbg !20
53 %2 = load i32, i32* @global3, align 4, !dbg !20
54 call void @llvm.dbg.value(metadata i32 %2, metadata !19, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32)), !dbg !20
55 tail call void @ext3(i32 %0, i32 %1, i32 %2) #3, !dbg !20
59 declare void @ext3(i32, i32, i32)
61 ; Function Attrs: nounwind readnone speculatable
62 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
64 attributes #0 = { nounwind uwtable }
65 attributes #1 = { nounwind readnone speculatable }
68 !llvm.module.flags = !{!5, !6}
71 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !3, nameTableKind: None)
72 !2 = !DIFile(filename: "foo.c", directory: "/")
74 !4 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
75 !5 = !{i32 2, !"Dwarf Version", i32 4}
76 !6 = !{i32 2, !"Debug Info Version", i32 3}
77 !7 = !{!"clang version 9.0.0"}
78 !8 = distinct !DISubprogram(name: "test1", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !11)
79 !9 = !DISubroutineType(types: !10)
82 !12 = !DILocalVariable(name: "local", scope: !8, file: !2, line: 8, type: !13)
83 !13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 96, elements: !14)
85 !15 = !DISubrange(count: 3)
86 !16 = !DILocation(line: 8, scope: !8)
87 !17 = !DILocation(line: 9, scope: !8)
88 !18 = distinct !DISubprogram(name: "test2", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !11)
89 !19 = !DILocalVariable(name: "local", scope: !18, file: !2, line: 8, type: !13)
90 !20 = !DILocation(line: 15, scope: !18)
91 !21 = !DILocation(line: 16, scope: !18)
96 tracksRegLiveness: true
99 frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
100 renamable $edi = MOV32rm $rip, 1, $noreg, @global1, $noreg, debug-location !16 :: (dereferenceable load 4 from @global1)
101 DBG_VALUE 456, $noreg, !12, !DIExpression(DW_OP_LLVM_fragment, 64, 32), debug-location !16
102 DBG_VALUE 123, $noreg, !12, !DIExpression(DW_OP_LLVM_fragment, 32, 32), debug-location !16
103 DBG_VALUE $edi, $noreg, !12, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !16
104 $esi = MOV32ri 123, debug-location !16
105 CALL64pcrel32 @ext2, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit killed $esi, implicit-def $rsp, implicit-def $ssp, debug-location !16
106 $eax = MOV32ri 123, debug-location !17
107 $rcx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !17
108 RETQ killed $eax, debug-location !17
113 # CHECK-NEXT: #DEBUG_VALUE: test1:local <- [DW_OP_LLVM_fragment 64 32] 456
114 # CHECK-NEXT: #DEBUG_VALUE: test1:local <- [DW_OP_LLVM_fragment 32 32] 123
115 # CHECK-NEXT: #DEBUG_VALUE: test1:local <- [DW_OP_LLVM_fragment 0 32] $edi
117 # CHECK-NEXT: .Ltmp2:
122 tracksRegLiveness: true
127 frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp, debug-location !20
128 renamable $ebx = MOV32rm $rip, 1, $noreg, @global1, $noreg, debug-location !20 :: (dereferenceable load 4 from @global1)
129 DBG_VALUE $ebx, $noreg, !19, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !20
130 renamable $esi = MOV32rm $rip, 1, $noreg, @global2, $noreg, debug-location !20 :: (dereferenceable load 4 from @global2)
131 DBG_VALUE $esi, $noreg, !19, !DIExpression(DW_OP_LLVM_fragment, 32, 32), debug-location !20
132 renamable $edx = MOV32rm $rip, 1, $noreg, @global3, $noreg, debug-location !20 :: (dereferenceable load 4 from @global3)
133 DBG_VALUE $edx, $noreg, !19, !DIExpression(DW_OP_LLVM_fragment, 64, 32), debug-location !20
134 $edi = MOV32rr $ebx, debug-location !20
135 CALL64pcrel32 @ext3, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit $esi, implicit $edx, implicit-def $rsp, implicit-def $ssp, debug-location !20
136 $eax = MOV32rr killed $ebx, debug-location !20
137 $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !20
138 RETQ killed $eax, debug-location !21
143 # CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 0 32] $ebx
145 # CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 32 32] $esi
147 # CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 64 32] $edx
149 # CHECK-NEXT: .Ltmp7:
151 # CHECK-NEXT: .Ltmp8:
153 #### Location list for test1:local.
155 # Verify that a location list entry, which does not contain the fragment that
156 # is described by the clobbered $edi, is emitted directly after the call to
159 # CHECK: .Ldebug_loc0:
160 # CHECK-NEXT: .quad .Ltmp1-.Lfunc_begin0
161 # CHECK-NEXT: .quad .Ltmp2-.Lfunc_begin0
162 # CHECK-NEXT: .short 14 # Loc expr size
163 # CHECK-NEXT: .byte 85 # super-register DW_OP_reg5
164 # CHECK-NEXT: .byte 147 # DW_OP_piece
165 # CHECK-NEXT: .byte 4 # 4
166 # CHECK-NEXT: .byte 16 # DW_OP_constu
167 # CHECK-NEXT: .byte 123 # 123
168 # CHECK-NEXT: .byte 159 # DW_OP_stack_value
169 # CHECK-NEXT: .byte 147 # DW_OP_piece
170 # CHECK-NEXT: .byte 4 # 4
171 # CHECK-NEXT: .byte 16 # DW_OP_constu
172 # CHECK-NEXT: .byte 200 # 456
173 # CHECK-NEXT: .byte 3 #
174 # CHECK-NEXT: .byte 159 # DW_OP_stack_value
175 # CHECK-NEXT: .byte 147 # DW_OP_piece
176 # CHECK-NEXT: .byte 4 # 4
177 # CHECK-NEXT: .quad .Ltmp2-.Lfunc_begin0
178 # CHECK-NEXT: .quad .Lfunc_end0-.Lfunc_begin0
179 # CHECK-NEXT: .short 13 # Loc expr size
180 # CHECK-NEXT: .byte 147 # DW_OP_piece
181 # CHECK-NEXT: .byte 4 # 4
182 # CHECK-NEXT: .byte 16 # DW_OP_constu
183 # CHECK-NEXT: .byte 123 # 123
184 # CHECK-NEXT: .byte 159 # DW_OP_stack_value
185 # CHECK-NEXT: .byte 147 # DW_OP_piece
186 # CHECK-NEXT: .byte 4 # 4
187 # CHECK-NEXT: .byte 16 # DW_OP_constu
188 # CHECK-NEXT: .byte 200 # 456
189 # CHECK-NEXT: .byte 3 #
190 # CHECK-NEXT: .byte 159 # DW_OP_stack_value
191 # CHECK-NEXT: .byte 147 # DW_OP_piece
192 # CHECK-NEXT: .byte 4 # 4
193 # CHECK-NEXT: .quad 0
194 # CHECK-NEXT: .quad 0
196 #### Location list for test2:local.
198 # Verify that the debug values that are described by $edi and $edx are
199 # considered clobbered by the call to ext3(), leaving a location list entry
200 # after the call where the first 32 bits are still described by $ebx.
201 # That location list entry is valid until the restore of the register.
203 # CHECK: .Ldebug_loc1:
204 # CHECK-NEXT: .quad .Ltmp4-.Lfunc_begin0
205 # CHECK-NEXT: .quad .Ltmp5-.Lfunc_begin0
206 # CHECK-NEXT: .short 3 # Loc expr size
207 # CHECK-NEXT: .byte 83 # super-register DW_OP_reg3
208 # CHECK-NEXT: .byte 147 # DW_OP_piece
209 # CHECK-NEXT: .byte 4 # 4
210 # CHECK-NEXT: .quad .Ltmp5-.Lfunc_begin0
211 # CHECK-NEXT: .quad .Ltmp6-.Lfunc_begin0
212 # CHECK-NEXT: .short 6 # Loc expr size
213 # CHECK-NEXT: .byte 83 # super-register DW_OP_reg3
214 # CHECK-NEXT: .byte 147 # DW_OP_piece
215 # CHECK-NEXT: .byte 4 # 4
216 # CHECK-NEXT: .byte 84 # super-register DW_OP_reg4
217 # CHECK-NEXT: .byte 147 # DW_OP_piece
218 # CHECK-NEXT: .byte 4 # 4
219 # CHECK-NEXT: .quad .Ltmp6-.Lfunc_begin0
220 # CHECK-NEXT: .quad .Ltmp7-.Lfunc_begin0
221 # CHECK-NEXT: .short 9 # Loc expr size
222 # CHECK-NEXT: .byte 83 # super-register DW_OP_reg3
223 # CHECK-NEXT: .byte 147 # DW_OP_piece
224 # CHECK-NEXT: .byte 4 # 4
225 # CHECK-NEXT: .byte 84 # super-register DW_OP_reg4
226 # CHECK-NEXT: .byte 147 # DW_OP_piece
227 # CHECK-NEXT: .byte 4 # 4
228 # CHECK-NEXT: .byte 81 # super-register DW_OP_reg1
229 # CHECK-NEXT: .byte 147 # DW_OP_piece
230 # CHECK-NEXT: .byte 4 # 4
231 # CHECK-NEXT: .quad .Ltmp7-.Lfunc_begin0
232 # CHECK-NEXT: .quad .Ltmp8-.Lfunc_begin0
233 # CHECK-NEXT: .short 3 # Loc expr size
234 # CHECK-NEXT: .byte 83 # super-register DW_OP_reg3
235 # CHECK-NEXT: .byte 147 # DW_OP_piece
236 # CHECK-NEXT: .byte 4 # 4
237 # CHECK-NEXT: .quad 0
238 # CHECK-NEXT: .quad 0