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