xref: /llvm-project/llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir (revision 624e52b1e310c349e21cc0b4f67452b0fa9d1f96)
1# RUN: llc %s -start-before=livedebugvalues -o - | \
2# RUN:     FileCheck %s --implicit-check-not=prologue_end
3#
4## When picking a "backup" location of the first non-trivial instruction in
5## a function, don't select a location outside of the entry block. We have to
6## give it the function's scope-line, and installing that outside of the entry
7## block is liable to be misleading.
8##
9## Produced from the C below with "clang -O2 -g -mllvm
10## -stop-before=livedebugvalues", then modified to unrotate and shift early
11## insts into the loop block. This means the MIR is meaningless, we only test
12## whether the scope-line will leak into the loop block or not.
13##
14## int glob = 0;
15## int foo(int arg, int sum) {
16##   arg += sum;
17##   while (arg) {
18##     glob--;
19##     arg %= glob;
20##   }
21##   return 0;
22## }
23#
24# CHECK-LABEL: foo:
25# CHECK:        .loc    0 2 0
26# CHECK:        # %bb.0:
27# CHECK-NEXT:   movl    %edi, %edx
28# CHECK-NEXT:   .loc    0 0 0 is_stmt 0
29# CHECK-NEXT:   .Ltmp0:
30# CHECK-NEXT:   .p2align        4
31# CHECK-NEXT:   .LBB0_1:
32# CHECK-LABEL:  addl    %esi, %edx
33
34## Second function in this file: test that we don't crash when having trailing
35## empty blocks and no location for a prologue. Test that a .loc is produced,
36## with an implicit-not check for there being no prologue_end.
37#
38# CHECK-LABEL: f:
39# CHECK: .loc    0 1234 0
40
41
42--- |
43  ; ModuleID = 'out2.ll'
44  source_filename = "foo.c"
45  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
46  target triple = "x86_64-unknown-linux-gnu"
47
48  @glob = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
49
50  define dso_local noundef i32 @foo(i32 noundef %arg, i32 noundef %sum) local_unnamed_addr !dbg !9 {
51  entry:
52    %add = add nsw i32 %sum, %arg
53    br label %while.body.preheader
54
55  while.body.preheader:                             ; preds = %entry
56    %glob.promoted = load i32, ptr @glob, align 4
57    br label %while.body, !dbg !13
58
59  while.body:                                       ; preds = %while.body, %while.body.preheader
60    %arg.addr.06 = phi i32 [ %rem, %while.body ], [ %add, %while.body.preheader ]
61    %dec35 = phi i32 [ %dec, %while.body ], [ %glob.promoted, %while.body.preheader ]
62    %dec = add nsw i32 %dec35, -1, !dbg !14
63    %0 = add i32 %dec35, -1, !dbg !16
64    %rem = srem i32 %arg.addr.06, %0, !dbg !16
65    %tobool.not = icmp eq i32 %rem, 0, !dbg !13
66    br i1 %tobool.not, label %while.cond.while.end_crit_edge, label %while.body, !dbg !13
67
68  while.cond.while.end_crit_edge:                   ; preds = %while.body
69    store i32 %dec, ptr @glob, align 4, !dbg !14
70    br label %while.end, !dbg !13
71
72  while.end:                                        ; preds = %while.cond.while.end_crit_edge
73    ret i32 0, !dbg !17
74  }
75
76  define void @f() !dbg !18 {
77  entry:
78    %0 = call ptr @llvm.returnaddress(i32 0)
79    br label %do.body
80
81  do.body:
82    unreachable
83  }
84
85  declare ptr @llvm.returnaddress(i32 immarg)
86
87  !llvm.dbg.cu = !{!2}
88  !llvm.module.flags = !{!6, !7}
89  !llvm.ident = !{!8}
90
91  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
92  !1 = distinct !DIGlobalVariable(name: "glob", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true)
93  !2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
94  !3 = !DIFile(filename: "foo.c", directory: "")
95  !4 = !{!0}
96  !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
97  !6 = !{i32 7, !"Dwarf Version", i32 5}
98  !7 = !{i32 2, !"Debug Info Version", i32 3}
99  !8 = !{!"clang"}
100  !9 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !12)
101  !10 = !DISubroutineType(types: !11)
102  !11 = !{!5, !5, !5}
103  !12 = !{}
104  !13 = !DILocation(line: 4, column: 3, scope: !9)
105  !14 = !DILocation(line: 5, column: 9, scope: !15)
106  !15 = distinct !DILexicalBlock(scope: !9, file: !3, line: 4, column: 15)
107  !16 = !DILocation(line: 6, column: 9, scope: !15)
108  !17 = !DILocation(line: 8, column: 3, scope: !9)
109  !18 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 37, type: !10, scopeLine: 1234, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
110
111...
112---
113name:            foo
114alignment:       16
115tracksRegLiveness: true
116debugInstrRef:   true
117tracksDebugUserValues: true
118liveins:
119  - { reg: '$edi' }
120  - { reg: '$esi' }
121frameInfo:
122  maxAlignment:    1
123  maxCallFrameSize: 0
124  isCalleeSavedInfoValid: true
125machineFunctionInfo:
126  amxProgModel:    None
127body:             |
128  bb.0.entry:
129    liveins: $edi, $esi
130
131    $edx = MOV32rr $edi
132
133  bb.1.while.body (align 16):
134    successors: %bb.2(0x04000000), %bb.1(0x7c000000)
135    liveins: $ecx, $edx, $esi
136
137    renamable $edx = nsw ADD32rr killed renamable $edx, renamable $esi, implicit-def dead $eflags
138    renamable $ecx = MOV32rm $rip, 1, $noreg, @glob, $noreg :: (dereferenceable load (s32) from @glob)
139    renamable $ecx = DEC32r killed renamable $ecx, implicit-def dead $eflags
140    $eax = MOV32rr killed $edx
141    CDQ implicit-def $eax, implicit-def $edx, implicit $eax
142    IDIV32r renamable $ecx, implicit-def dead $eax, implicit-def $edx, implicit-def dead $eflags, implicit $eax, implicit $edx
143    TEST32rr renamable $edx, renamable $edx, implicit-def $eflags
144    JCC_1 %bb.1, 5, implicit killed $eflags
145
146  bb.2.while.cond.while.end_crit_edge:
147    liveins: $ecx, $esi
148
149    MOV32mr $rip, 1, $noreg, @glob, $noreg, killed renamable $ecx, debug-location !14 :: (store (s32) into @glob)
150    $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !17
151    RET64 $eax, debug-location !17
152
153...
154---
155name:            f
156alignment:       16
157tracksRegLiveness: true
158noPhis:          true
159isSSA:           false
160noVRegs:         true
161hasFakeUses:     false
162tracksDebugUserValues: true
163frameInfo:
164  stackSize:       8
165  offsetAdjustment: -8
166  maxAlignment:    1
167  maxCallFrameSize: 0
168  isCalleeSavedInfoValid: true
169fixedStack:
170  - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 }
171machineFunctionInfo:
172  amxProgModel:    None
173body:             |
174  bb.0.entry:
175    frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
176    frame-setup CFI_INSTRUCTION def_cfa_offset 16
177    frame-setup CFI_INSTRUCTION offset $rbp, -16
178    $rbp = frame-setup MOV64rr $rsp
179    frame-setup CFI_INSTRUCTION def_cfa_register $rbp
180
181  bb.1.do.body:
182
183...
184