xref: /llvm-project/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir (revision 92b33822e989884d29465d34769b07d78aeb1a84)
1# RUN: llc -O1 -start-after=livedebugvalues -o - %s | FileCheck %s
2
3# Reproducer based on the following C file:
4#
5# int global1, global2, global3;
6#
7# extern void ext1(int);
8# extern void ext2(int, int);
9# extern void ext3(int, int, int);
10#
11# int test1() {
12#   int local[3] = {global1, 123, 456};
13#   ext2(local[0], local[1]);
14#   return local[1];
15# }
16#
17# int test2() {
18#   int local[3] = {global1, global2, global3};
19#   ext3(local[0], local[1], local[2]);
20#   return local[0];
21# }
22#
23# Compiled using -O1 -g.
24
25--- |
26  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
27  target triple = "x86_64-unknown-linux-gnu"
28
29  @global1 = common global i32 0, align 4
30  @global2 = common global i32 0, align 4
31  @global3 = common global i32 0, align 4
32
33  ; Function Attrs: nounwind uwtable
34  define i32 @test1() #0 !dbg !8 {
35  entry:
36    %0 = load i32, ptr @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
41    ret i32 123, !dbg !17
42  }
43
44  declare void @ext2(i32, i32)
45
46  ; Function Attrs: nounwind uwtable
47  define i32 @test2() #0 !dbg !18 {
48  entry:
49    %0 = load i32, ptr @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, ptr @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, ptr @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
56    ret i32 %0, !dbg !21
57  }
58
59  declare void @ext3(i32, i32, i32)
60
61  ; Function Attrs: nounwind readnone speculatable
62  declare void @llvm.dbg.value(metadata, metadata, metadata) #1
63
64  attributes #0 = { nounwind uwtable }
65  attributes #1 = { nounwind readnone speculatable }
66
67  !llvm.dbg.cu = !{!1}
68  !llvm.module.flags = !{!5, !6}
69  !llvm.ident = !{!7}
70
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: "/")
73  !3 = !{}
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)
80  !10 = !{!4}
81  !11 = !{!12}
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)
84  !14 = !{!15}
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)
92
93...
94---
95name:            test1
96tracksRegLiveness: true
97body:             |
98  bb.0.entry:
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 (s32) 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    RET64 killed $eax, debug-location !17
109
110...
111
112# CHECK: .Ltmp1
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
116# CHECK:         callq   ext2
117# CHECK-NEXT: .Ltmp2:
118
119...
120---
121name:            test2
122tracksRegLiveness: true
123body:             |
124  bb.0.entry:
125    liveins: $rbx
126
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 (s32) 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 (s32) 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 (s32) 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    RET64 killed $eax, debug-location !21
139
140...
141
142# CHECK: .Ltmp4:
143# CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 0 32] $ebx
144# CHECK: .Ltmp5:
145# CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 32 32] $esi
146# CHECK: .Ltmp6:
147# CHECK-NEXT: #DEBUG_VALUE: test2:local <- [DW_OP_LLVM_fragment 64 32] $edx
148# CHECK:         callq   ext3
149# CHECK-NEXT: .Ltmp7:
150# CHECK:         popq    %rbx
151# CHECK-NEXT: .Ltmp8:
152
153#### Location list for test1:local.
154
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
157# ext2().
158
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
195
196#### Location list for test2:local.
197
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.
202
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
239