1; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim -tailcallopt | FileCheck %s -check-prefix CHECK-TAIL
2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim | FileCheck %s
3; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim -tailcallopt -aarch64-redzone | FileCheck %s -check-prefix CHECK-TAIL-RZ
4
5; Without tailcallopt fastcc still means the caller cleans up the
6; stack, so try to make sure this is respected.
7
8define fastcc void @func_stack0() {
9; CHECK-LABEL: func_stack0:
10; CHECK: mov x29, sp
11; CHECK: str w{{[0-9]+}}, [sp, #-32]!
12
13; CHECK-TAIL-LABEL: func_stack0:
14; CHECK-TAIL: stp x29, x30, [sp, #-16]!
15; CHECK-TAIL-NEXT: mov x29, sp
16; CHECK-TAIL: str w{{[0-9]+}}, [sp, #-32]!
17
18
19  call fastcc void @func_stack8([8 x i32] undef, i32 42)
20; CHECK:  bl func_stack8
21; CHECK-NOT: sub sp, sp,
22
23; CHECK-TAIL: bl func_stack8
24; CHECK-TAIL: sub sp, sp, #16
25
26
27  call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
28; CHECK: bl func_stack32
29; CHECK-NOT: sub sp, sp,
30
31
32; CHECK-TAIL: bl func_stack32
33; CHECK-TAIL: sub sp, sp, #32
34
35
36  call fastcc void @func_stack0()
37; CHECK: bl func_stack0
38; CHECK-NOT: sub sp, sp
39
40
41; CHECK-TAIL: bl func_stack0
42; CHECK-TAIL-NOT: sub sp, sp
43
44  ret void
45; CHECK: add sp, sp, #32
46; CHECK-NEXT: ldp     x29, x30, [sp], #16
47; CHECK-NEXT: ret
48
49
50; CHECK-TAIL: add sp, sp, #32
51; CHECK-TAIL-NEXT: ldp     x29, x30, [sp], #16
52; CHECK-TAIL-NEXT: ret
53}
54
55define fastcc void @func_stack8([8 x i32], i32 %stacked) {
56; CHECK-LABEL: func_stack8:
57; CHECK: stp x29, x30, [sp, #-16]!
58; CHECK: mov x29, sp
59; CHECK: str w{{[0-9]+}}, [sp, #-32]!
60
61
62; CHECK-TAIL-LABEL: func_stack8:
63; CHECK-TAIL: stp x29, x30, [sp, #-16]!
64; CHECK-TAIL: mov x29, sp
65; CHECK-TAIL: str w{{[0-9]+}}, [sp, #-32]!
66
67
68  call fastcc void @func_stack8([8 x i32] undef, i32 42)
69; CHECK:  bl func_stack8
70; CHECK-NOT: sub sp, sp,
71
72
73; CHECK-TAIL: bl func_stack8
74; CHECK-TAIL: sub sp, sp, #16
75
76
77  call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
78; CHECK: bl func_stack32
79; CHECK-NOT: sub sp, sp,
80
81
82; CHECK-TAIL: bl func_stack32
83; CHECK-TAIL: sub sp, sp, #32
84
85
86  call fastcc void @func_stack0()
87; CHECK: bl func_stack0
88; CHECK-NOT: sub sp, sp
89
90; CHECK-TAIL: bl func_stack0
91; CHECK-TAIL-NOT: sub sp, sp
92
93  ret void
94; CHECK: add sp, sp, #32
95; CHECK-NEXT: ldp     x29, x30, [sp], #16
96; CHECK-NEXT: ret
97
98
99; CHECK-TAIL: add sp, sp, #32
100; CHECK-TAIL-NEXT: ldp     x29, x30, [sp], #16
101; CHECK-TAIL-NEXT: add     sp, sp, #16
102; CHECK-TAIL-NEXT: ret
103}
104
105define fastcc void @func_stack32([8 x i32], i128 %stacked0, i128 %stacked1) {
106; CHECK-LABEL: func_stack32:
107; CHECK: mov x29, sp
108
109; CHECK-TAIL-LABEL: func_stack32:
110; CHECK-TAIL: mov x29, sp
111
112
113  call fastcc void @func_stack8([8 x i32] undef, i32 42)
114; CHECK:  bl func_stack8
115; CHECK-NOT: sub sp, sp,
116
117; CHECK-TAIL: bl func_stack8
118; CHECK-TAIL: sub sp, sp, #16
119
120
121  call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9)
122; CHECK: bl func_stack32
123; CHECK-NOT: sub sp, sp,
124
125
126; CHECK-TAIL: bl func_stack32
127; CHECK-TAIL: sub sp, sp, #32
128
129
130  call fastcc void @func_stack0()
131; CHECK: bl func_stack0
132; CHECK-NOT: sub sp, sp
133
134
135; CHECK-TAIL: bl func_stack0
136; CHECK-TAIL-NOT: sub sp, sp
137
138  ret void
139; CHECK: add sp, sp, #32
140; CHECK-NEXT: ldp     x29, x30, [sp], #16
141; CHECK-NEXT: ret
142
143; CHECK-TAIL: add sp, sp, #32
144; CHECK-TAIL-NEXT: ldp     x29, x30, [sp], #16
145; CHECK-TAIL-NEXT: add     sp, sp, #32
146; CHECK-TAIL-NEXT: ret
147}
148
149; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
150define fastcc void @func_stack32_leaf([8 x i32], i128 %stacked0, i128 %stacked1) {
151; CHECK-LABEL: func_stack32_leaf:
152; CHECK: str     x20, [sp, #-16]!
153; CHECK: nop
154; CHECK-NEXT: //NO_APP
155; CHECK-NEXT: ldr     x20, [sp], #16
156; CHECK-NEXT: ret
157
158; CHECK-TAIL-LABEL: func_stack32_leaf:
159; CHECK-TAIL: str     x20, [sp, #-16]!
160; CHECK-TAIL: nop
161; CHECK-TAIL-NEXT: //NO_APP
162; CHECK-TAIL-NEXT: ldr     x20, [sp], #16
163; CHECK-TAIL-NEXT: add     sp, sp, #32
164; CHECK-TAIL-NEXT: ret
165
166; CHECK-TAIL-RZ-LABEL: func_stack32_leaf:
167; CHECK-TAIL-RZ: str     x20, [sp, #-16]!
168; CHECK-TAIL-RZ-NOT: sub     sp, sp
169; CHECK-TAIL-RZ: nop
170; CHECK-TAIL-RZ-NEXT: //NO_APP
171; CHECK-TAIL-RZ-NEXT: ldr     x20, [sp], #16
172; CHECK-TAIL-RZ-NEXT: add     sp, sp, #32
173; CHECK-TAIL-RZ-NEXT: ret
174
175  ; Make sure there is a callee-save register to save/restore.
176  call void asm sideeffect "nop", "~{x20}"() nounwind
177  ret void
178}
179
180; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
181define fastcc void @func_stack32_leaf_local([8 x i32], i128 %stacked0, i128 %stacked1) {
182; CHECK-LABEL: func_stack32_leaf_local:
183; CHECK: str     x20, [sp, #-16]!
184; CHECK-NEXT: sub     sp, sp, #16
185; CHECK: nop
186; CHECK-NEXT: //NO_APP
187; CHECK-NEXT: add     sp, sp, #16
188; CHECK-NEXT: ldr     x20, [sp], #16
189; CHECK-NEXT: ret
190
191; CHECK-TAIL-LABEL: func_stack32_leaf_local:
192; CHECK-TAIL: str     x20, [sp, #-16]!
193; CHECK-TAIL-NEXT: sub     sp, sp, #16
194; CHECK-TAIL: nop
195; CHECK-TAIL-NEXT: //NO_APP
196; CHECK-TAIL-NEXT: add     sp, sp, #16
197; CHECK-TAIL-NEXT: ldr     x20, [sp], #16
198; CHECK-TAIL-NEXT: add     sp, sp, #32
199; CHECK-TAIL-NEXT: ret
200
201; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local:
202; CHECK-TAIL-RZ: str     x20, [sp, #-16]!
203; CHECK-TAIL-RZ-NOT: sub     sp, sp
204; CHECK-TAIL-RZ: nop
205; CHECK-TAIL-RZ-NEXT: //NO_APP
206; CHECK-TAIL-RZ-NEXT: ldr     x20, [sp], #16
207; CHECK-TAIL-RZ-NEXT: add     sp, sp, #32
208; CHECK-TAIL-RZ-NEXT: ret
209
210  %val0 = alloca [2 x i64], align 8
211
212  ; Make sure there is a callee-save register to save/restore.
213  call void asm sideeffect "nop", "~{x20}"() nounwind
214  ret void
215}
216
217; Check that arg stack pop is done after callee-save restore when no frame pointer is used.
218define fastcc void @func_stack32_leaf_local_nocs([8 x i32], i128 %stacked0, i128 %stacked1) {
219; CHECK-LABEL: func_stack32_leaf_local_nocs:
220; CHECK: sub     sp, sp, #16
221; CHECK: add     sp, sp, #16
222; CHECK-NEXT: ret
223
224; CHECK-TAIL-LABEL: func_stack32_leaf_local_nocs:
225; CHECK-TAIL: sub     sp, sp, #16
226; CHECK-TAIL: add     sp, sp, #48
227; CHECK-TAIL-NEXT: ret
228
229; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local_nocs:
230; CHECK-TAIL-RZ: add     sp, sp, #32
231; CHECK-TAIL-RZ-NEXT: ret
232
233  %val0 = alloca [2 x i64], align 8
234
235  ret void
236}
237