1; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -disable-post-ra < %s | FileCheck %s
2; RUN: llc -verify-machineinstrs -mtriple=arm64-apple-ios -disable-post-ra < %s | FileCheck %s --check-prefix=CHECK-MACHO
3
4; This test aims to check basic correctness of frame layout &
5; frame access code. There are 8 functions in this test file,
6; each function implements one element in the cartesian product
7; of:
8; . a function having a VLA/noVLA
9; . a function with dynamic stack realignment/no dynamic stack realignment.
10; . a function needing a frame pionter/no frame pointer,
11; since the presence/absence of these has influence on the frame
12; layout and which pointer to use to access various part of the
13; frame (bp,sp,fp).
14;
15; Furthermore: in every test function:
16; . there is always one integer and 1 floating point argument to be able
17;   to check those are accessed correctly.
18; . there is always one local variable to check that is accessed
19;   correctly
20;
21; The LLVM-IR below was produced by clang on the following C++ code:
22;extern "C" int g();
23;extern "C" int novla_nodynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
24;                                             double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
25;{
26;  // use an argument passed on the stack.
27;  volatile int l1;
28;  return i10 + (int)d10 + l1 + g();
29;}
30;extern "C" int novla_nodynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
31;                                             double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
32;{
33;  // use an argument passed on the stack.
34;  volatile int l1;
35;  return i10 + (int)d10 + l1;
36;}
37;extern "C" int novla_dynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
38;                                         double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
39;{
40;  // use an argument passed on the stack.
41;  alignas(128) volatile int l1;
42;  return i10 + (int)d10 + l1 + g();
43;}
44;extern "C" int novla_dynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
45;                                           double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
46;{
47;  // use an argument passed on the stack.
48;  alignas(128) volatile int l1;
49;  return i10 + (int)d10 + l1;
50;}
51;
52;extern "C" int vla_nodynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
53;                                         double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
54;{
55;  // use an argument passed on the stack.
56;  volatile int l1;
57;  volatile int vla[i1];
58;  return i10 + (int)d10 + l1 + g() + vla[0];
59;}
60;extern "C" int vla_nodynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
61;                                           double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
62;{
63;  // use an argument passed on the stack.
64;  volatile int l1;
65;  volatile int vla[i1];
66;  return i10 + (int)d10 + l1 + vla[0];
67;}
68;extern "C" int vla_dynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
69;                                       double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
70;{
71;  // use an argument passed on the stack.
72;  alignas(128) volatile int l1;
73;  volatile int vla[i1];
74;  return i10 + (int)d10 + l1 + g() + vla[0];
75;}
76;extern "C" int vla_dynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
77;                                         double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
78;{
79;  // use an argument passed on the stack.
80;  alignas(128) volatile int l1;
81;  volatile int vla[i1];
82;  return i10 + (int)d10 + l1 + vla[0];
83;}
84
85
86
87define i32 @novla_nodynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 {
88entry:
89  %l1 = alloca i32, align 4
90  %conv = fptosi double %d10 to i32
91  %add = add nsw i32 %conv, %i10
92  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
93  %add1 = add nsw i32 %add, %l1.0.l1.0.
94  %call = tail call i32 @g()
95  %add2 = add nsw i32 %add1, %call
96  ret i32 %add2
97}
98; CHECK-LABEL: novla_nodynamicrealign_call
99; CHECK: .cfi_startproc
100;   Check that used callee-saved registers are saved
101; CHECK: str	x19, [sp, #-32]!
102;   Check that the frame pointer is created:
103; CHECK: stp	x29, x30, [sp, #16]
104; CHECK: add	x29, sp, #16
105;   Check correctness of cfi pseudo-instructions
106; CHECK: .cfi_def_cfa w29, 16
107; CHECK: .cfi_offset w30, -8
108; CHECK: .cfi_offset w29, -16
109; CHECK: .cfi_offset w19, -32
110;   Check correct access to arguments passed on the stack, through frame pointer
111; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
112; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
113;   Check correct access to local variable on the stack, through stack pointer
114; CHECK: ldr	w[[ILOC:[0-9]+]], [sp, #12]
115;   Check epilogue:
116; CHECK: ldp	x29, x30, [sp, #16]
117; CHECK: ldr	x19, [sp], #32
118; CHECK: ret
119; CHECK: .cfi_endproc
120
121; CHECK-MACHO-LABEL: _novla_nodynamicrealign_call:
122; CHECK-MACHO: .cfi_startproc
123;   Check that used callee-saved registers are saved
124; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
125;   Check that the frame pointer is created:
126; CHECK-MACHO: stp	x29, x30, [sp, #16]
127; CHECK-MACHO: add	x29, sp, #16
128;   Check correctness of cfi pseudo-instructions
129; CHECK-MACHO: .cfi_def_cfa w29, 16
130; CHECK-MACHO: .cfi_offset w30, -8
131; CHECK-MACHO: .cfi_offset w29, -16
132; CHECK-MACHO: .cfi_offset w19, -24
133; CHECK-MACHO: .cfi_offset w20, -32
134;   Check correct access to arguments passed on the stack, through frame pointer
135; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
136; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
137;   Check correct access to local variable on the stack, through stack pointer
138; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [sp, #12]
139;   Check epilogue:
140; CHECK-MACHO: ldp	x29, x30, [sp, #16]
141; CHECK-MACHO: ldp	x20, x19, [sp], #32
142; CHECK-MACHO: ret
143; CHECK-MACHO: .cfi_endproc
144
145
146declare i32 @g() #0
147
148; Function Attrs: nounwind
149define i32 @novla_nodynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 {
150entry:
151  %l1 = alloca i32, align 4
152  %conv = fptosi double %d10 to i32
153  %add = add nsw i32 %conv, %i10
154  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
155  %add1 = add nsw i32 %add, %l1.0.l1.0.
156  ret i32 %add1
157}
158; CHECK-LABEL: novla_nodynamicrealign_nocall
159;   Check that space is reserved for one local variable on the stack.
160; CHECK:	sub	sp, sp, #16             // =16
161;   Check correct access to arguments passed on the stack, through stack pointer
162; CHECK: ldr	d[[DARG:[0-9]+]], [sp, #40]
163; CHECK: ldr	w[[IARG:[0-9]+]], [sp, #24]
164;   Check correct access to local variable on the stack, through stack pointer
165; CHECK: ldr	w[[ILOC:[0-9]+]], [sp, #12]
166;   Check epilogue:
167; CHECK: add	sp, sp, #16             // =16
168; CHECK: ret
169
170
171define i32 @novla_dynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 {
172entry:
173  %l1 = alloca i32, align 128
174  %conv = fptosi double %d10 to i32
175  %add = add nsw i32 %conv, %i10
176  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
177  %add1 = add nsw i32 %add, %l1.0.l1.0.
178  %call = tail call i32 @g()
179  %add2 = add nsw i32 %add1, %call
180  ret i32 %add2
181}
182
183; CHECK-LABEL: novla_dynamicrealign_call
184; CHECK: .cfi_startproc
185;   Check that used callee-saved registers are saved
186; CHECK: str	x19, [sp, #-32]!
187;   Check that the frame pointer is created:
188; CHECK: stp	x29, x30, [sp, #16]
189; CHECK: add	x29, sp, #16
190;   Check the dynamic realignment of the stack pointer to a 128-byte boundary
191; CHECK: sub	x9, sp, #96
192; CHECK: and	sp, x9, #0xffffffffffffff80
193;   Check correctness of cfi pseudo-instructions
194; CHECK: .cfi_def_cfa w29, 16
195; CHECK: .cfi_offset w30, -8
196; CHECK: .cfi_offset w29, -16
197; CHECK: .cfi_offset w19, -32
198;   Check correct access to arguments passed on the stack, through frame pointer
199; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
200; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
201;   Check correct access to local variable on the stack, through re-aligned stack pointer
202; CHECK: ldr	w[[ILOC:[0-9]+]], [sp]
203;   Check epilogue:
204;     Check that stack pointer get restored from frame pointer.
205; CHECK: sub	sp, x29, #16            // =16
206; CHECK: ldp	x29, x30, [sp, #16]
207; CHECK: ldr	x19, [sp], #32
208; CHECK: ret
209; CHECK: .cfi_endproc
210
211; CHECK-MACHO-LABEL: _novla_dynamicrealign_call:
212; CHECK-MACHO: .cfi_startproc
213;   Check that used callee-saved registers are saved
214; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
215;   Check that the frame pointer is created:
216; CHECK-MACHO: stp	x29, x30, [sp, #16]
217; CHECK-MACHO: add	x29, sp, #16
218;   Check the dynamic realignment of the stack pointer to a 128-byte boundary
219; CHECK-MACHO: sub	x9, sp, #96
220; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
221;   Check correctness of cfi pseudo-instructions
222; CHECK-MACHO: .cfi_def_cfa w29, 16
223; CHECK-MACHO: .cfi_offset w30, -8
224; CHECK-MACHO: .cfi_offset w29, -16
225; CHECK-MACHO: .cfi_offset w19, -24
226; CHECK-MACHO: .cfi_offset w20, -32
227;   Check correct access to arguments passed on the stack, through frame pointer
228; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
229; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
230;   Check correct access to local variable on the stack, through re-aligned stack pointer
231; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [sp]
232;   Check epilogue:
233;     Check that stack pointer get restored from frame pointer.
234; CHECK-MACHO: sub	sp, x29, #16
235; CHECK-MACHO: ldp	x29, x30, [sp, #16]
236; CHECK-MACHO: ldp	x20, x19, [sp], #32
237; CHECK-MACHO: ret
238; CHECK-MACHO: .cfi_endproc
239
240
241; Function Attrs: nounwind
242define i32 @novla_dynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 {
243entry:
244  %l1 = alloca i32, align 128
245  %conv = fptosi double %d10 to i32
246  %add = add nsw i32 %conv, %i10
247  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
248  %add1 = add nsw i32 %add, %l1.0.l1.0.
249  ret i32 %add1
250}
251
252; CHECK-LABEL: novla_dynamicrealign_nocall
253;   Check that the frame pointer is created:
254; CHECK: stp	x29, x30, [sp, #-16]!
255; CHECK: mov	x29, sp
256;   Check the dynamic realignment of the stack pointer to a 128-byte boundary
257; CHECK: sub	x9, sp, #112
258; CHECK: and	sp, x9, #0xffffffffffffff80
259;   Check correct access to arguments passed on the stack, through frame pointer
260; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
261; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
262;   Check correct access to local variable on the stack, through re-aligned stack pointer
263; CHECK: ldr	w[[ILOC:[0-9]+]], [sp]
264;   Check epilogue:
265;     Check that stack pointer get restored from frame pointer.
266; CHECK: mov	sp, x29
267; CHECK: ldp	x29, x30, [sp], #16
268; CHECK: ret
269
270
271define i32 @vla_nodynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 {
272entry:
273  %l1 = alloca i32, align 4
274  %0 = zext i32 %i1 to i64
275  %vla = alloca i32, i64 %0, align 4
276  %conv = fptosi double %d10 to i32
277  %add = add nsw i32 %conv, %i10
278  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
279  %add1 = add nsw i32 %add, %l1.0.l1.0.
280  %call = tail call i32 @g()
281  %add2 = add nsw i32 %add1, %call
282  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
283  %add3 = add nsw i32 %add2, %1
284  ret i32 %add3
285}
286
287; CHECK-LABEL: vla_nodynamicrealign_call
288; CHECK: .cfi_startproc
289;   Check that used callee-saved registers are saved
290; CHECK: stp	x20, x19, [sp, #-32]!
291;   Check that the frame pointer is created:
292; CHECK: stp	x29, x30, [sp, #16]
293; CHECK: add	x29, sp, #16
294;   Check that space is reserved on the stack for the local variable,
295;   rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
296; CHECK: sub	sp, sp, #16
297;   Check correctness of cfi pseudo-instructions
298; CHECK: .cfi_def_cfa w29, 16
299; CHECK: .cfi_offset w30, -8
300; CHECK: .cfi_offset w29, -16
301; CHECK: .cfi_offset w19, -24
302; CHECK: .cfi_offset w20, -32
303;   Check correct access to arguments passed on the stack, through frame pointer
304; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
305; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
306;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
307; CHECK: mov	w9, w0
308; CHECK: mov	 x10, sp
309; CHECK: lsl	x9, x9, #2
310; CHECK: add	x9, x9, #15
311; CHECK: and	x9, x9, #0x7fffffff0
312; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
313; CHECK: mov	 sp, x[[VLASPTMP]]
314;   Check correct access to local variable, through frame pointer
315; CHECK: ldur	w[[ILOC:[0-9]+]], [x29, #-20]
316;   Check correct accessing of the VLA variable through the base pointer
317; CHECK: ldr	w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
318;   Check epilogue:
319;     Check that stack pointer get restored from frame pointer.
320; CHECK: sub	sp, x29, #16            // =16
321; CHECK: ldp	x29, x30, [sp, #16]
322; CHECK: ldp	x20, x19, [sp], #32
323; CHECK: ret
324; CHECK: .cfi_endproc
325
326
327; Function Attrs: nounwind
328define i32 @vla_nodynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 {
329entry:
330  %l1 = alloca i32, align 4
331  %0 = zext i32 %i1 to i64
332  %vla = alloca i32, i64 %0, align 4
333  %conv = fptosi double %d10 to i32
334  %add = add nsw i32 %conv, %i10
335  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
336  %add1 = add nsw i32 %add, %l1.0.l1.0.
337  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
338  %add2 = add nsw i32 %add1, %1
339  ret i32 %add2
340}
341
342; CHECK-LABEL: vla_nodynamicrealign_nocall
343;   Check that the frame pointer is created:
344; CHECK: stp	x29, x30, [sp, #-16]!
345; CHECK: mov	x29, sp
346;   Check that space is reserved on the stack for the local variable,
347;   rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
348; CHECK: sub	sp, sp, #16
349;   Check correctness of cfi pseudo-instructions
350;   Check correct access to arguments passed on the stack, through frame pointer
351; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
352; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
353;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
354; CHECK: mov	w9, w0
355; CHECK: mov	 x10, sp
356; CHECK: lsl	x9, x9, #2
357; CHECK: add	x9, x9, #15
358; CHECK: and	x9, x9, #0x7fffffff0
359; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
360; CHECK: mov	 sp, x[[VLASPTMP]]
361;   Check correct access to local variable, through frame pointer
362; CHECK: ldur	w[[ILOC:[0-9]+]], [x29, #-4]
363;   Check correct accessing of the VLA variable through the base pointer
364; CHECK: ldr	w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
365;   Check epilogue:
366;     Check that stack pointer get restored from frame pointer.
367; CHECK: mov    sp, x29
368; CHECK: ldp	x29, x30, [sp], #16
369; CHECK: ret
370
371
372define i32 @vla_dynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 {
373entry:
374  %l1 = alloca i32, align 128
375  %0 = zext i32 %i1 to i64
376  %vla = alloca i32, i64 %0, align 4
377  %conv = fptosi double %d10 to i32
378  %add = add nsw i32 %conv, %i10
379  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
380  %add1 = add nsw i32 %add, %l1.0.l1.0.
381  %call = tail call i32 @g()
382  %add2 = add nsw i32 %add1, %call
383  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
384  %add3 = add nsw i32 %add2, %1
385  ret i32 %add3
386}
387
388; CHECK-LABEL: vla_dynamicrealign_call
389; CHECK: .cfi_startproc
390;   Check that used callee-saved registers are saved
391; CHECK: str	x21, [sp, #-48]!
392; CHECK: stp	x20, x19, [sp, #16]
393;   Check that the frame pointer is created:
394; CHECK: stp	x29, x30, [sp, #32]
395; CHECK: add	x29, sp, #32
396;   Check that the stack pointer gets re-aligned to 128
397;   bytes & the base pointer (x19) gets initialized to
398;   this 128-byte aligned area for local variables &
399;   spill slots
400; CHECK: sub	x9, sp, #80            // =80
401; CHECK: and	sp, x9, #0xffffffffffffff80
402; CHECK: mov    x19, sp
403;   Check correctness of cfi pseudo-instructions
404; CHECK: .cfi_def_cfa w29, 16
405; CHECK: .cfi_offset w30, -8
406; CHECK: .cfi_offset w29, -16
407; CHECK: .cfi_offset w19, -24
408; CHECK: .cfi_offset w20, -32
409; CHECK: .cfi_offset w21, -48
410;   Check correct access to arguments passed on the stack, through frame pointer
411; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
412; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
413;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
414;   and set-up of base pointer (x19).
415; CHECK: mov	w9, w0
416; CHECK: mov	 x10, sp
417; CHECK: lsl	x9, x9, #2
418; CHECK: add	x9, x9, #15
419; CHECK: and	x9, x9, #0x7fffffff0
420; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
421; CHECK: mov	 sp, x[[VLASPTMP]]
422;   Check correct access to local variable, through base pointer
423; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
424; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
425;   Check epilogue:
426;     Check that stack pointer get restored from frame pointer.
427; CHECK: sub	sp, x29, #32
428; CHECK: ldp	x29, x30, [sp, #32]
429; CHECK: ldp	x20, x19, [sp, #16]
430; CHECK: ldr	x21, [sp], #48
431; CHECK: ret
432; CHECK: .cfi_endproc
433
434; CHECK-MACHO-LABEL: _vla_dynamicrealign_call:
435; CHECK-MACHO: .cfi_startproc
436;   Check that used callee-saved registers are saved
437; CHECK-MACHO: stp	x22, x21, [sp, #-48]!
438; CHECK-MACHO: stp	x20, x19, [sp, #16]
439;   Check that the frame pointer is created:
440; CHECK-MACHO: stp	x29, x30, [sp, #32]
441; CHECK-MACHO: add	x29, sp, #32
442;   Check that the stack pointer gets re-aligned to 128
443;   bytes & the base pointer (x19) gets initialized to
444;   this 128-byte aligned area for local variables &
445;   spill slots
446; CHECK-MACHO: sub	x9, sp, #80
447; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
448; CHECK-MACHO: mov    x19, sp
449;   Check correctness of cfi pseudo-instructions
450; CHECK-MACHO: .cfi_def_cfa w29, 16
451; CHECK-MACHO: .cfi_offset w30, -8
452; CHECK-MACHO: .cfi_offset w29, -16
453; CHECK-MACHO: .cfi_offset w19, -24
454; CHECK-MACHO: .cfi_offset w20, -32
455; CHECK-MACHO: .cfi_offset w21, -40
456; CHECK-MACHO: .cfi_offset w22, -48
457;   Check correct access to arguments passed on the stack, through frame pointer
458; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
459; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
460;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
461;   and set-up of base pointer (x19).
462; CHECK-MACHO: mov	w9, w0
463; CHECK-MACHO: mov	 x10, sp
464; CHECK-MACHO: lsl	x9, x9, #2
465; CHECK-MACHO: add	x9, x9, #15
466; CHECK-MACHO: and	x9, x9, #0x7fffffff0
467; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
468; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
469;   Check correct access to local variable, through base pointer
470; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
471; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
472;   Check epilogue:
473;     Check that stack pointer get restored from frame pointer.
474; CHECK-MACHO: sub	sp, x29, #32
475; CHECK-MACHO: ldp	x29, x30, [sp, #32]
476; CHECK-MACHO: ldp	x20, x19, [sp, #16]
477; CHECK-MACHO: ldp	x22, x21, [sp], #48
478; CHECK-MACHO: ret
479; CHECK-MACHO: .cfi_endproc
480
481
482; Function Attrs: nounwind
483define i32 @vla_dynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 {
484entry:
485  %l1 = alloca i32, align 128
486  %0 = zext i32 %i1 to i64
487  %vla = alloca i32, i64 %0, align 4
488  %conv = fptosi double %d10 to i32
489  %add = add nsw i32 %conv, %i10
490  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
491  %add1 = add nsw i32 %add, %l1.0.l1.0.
492  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
493  %add2 = add nsw i32 %add1, %1
494  ret i32 %add2
495}
496
497; CHECK-LABEL: vla_dynamicrealign_nocall
498;   Check that used callee-saved registers are saved
499; CHECK: str	x19, [sp, #-32]!
500;   Check that the frame pointer is created:
501; CHECK: stp	x29, x30, [sp, #16]
502; CHECK: add	x29, sp, #16
503;   Check that the stack pointer gets re-aligned to 128
504;   bytes & the base pointer (x19) gets initialized to
505;   this 128-byte aligned area for local variables &
506;   spill slots
507; CHECK: sub	x9, sp, #96
508; CHECK: and	sp, x9, #0xffffffffffffff80
509; CHECK: mov    x19, sp
510;   Check correct access to arguments passed on the stack, through frame pointer
511; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
512; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
513;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
514;   and set-up of base pointer (x19).
515; CHECK: mov	w9, w0
516; CHECK: mov	 x10, sp
517; CHECK: lsl	x9, x9, #2
518; CHECK: add	x9, x9, #15
519; CHECK: and	x9, x9, #0x7fffffff0
520; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
521; CHECK: mov	 sp, x[[VLASPTMP]]
522;   Check correct access to local variable, through base pointer
523; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
524; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
525;   Check epilogue:
526;     Check that stack pointer get restored from frame pointer.
527; CHECK: sub	sp, x29, #16
528; CHECK: ldp	x29, x30, [sp, #16]
529; CHECK: ldr	x19, [sp], #32
530; CHECK: ret
531
532; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall:
533;   Check that used callee-saved registers are saved
534; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
535;   Check that the frame pointer is created:
536; CHECK-MACHO: stp	x29, x30, [sp, #16]
537; CHECK-MACHO: add	x29, sp, #16
538;   Check that the stack pointer gets re-aligned to 128
539;   bytes & the base pointer (x19) gets initialized to
540;   this 128-byte aligned area for local variables &
541;   spill slots
542; CHECK-MACHO: sub	x9, sp, #96
543; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
544; CHECK-MACHO: mov    x19, sp
545;   Check correct access to arguments passed on the stack, through frame pointer
546; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
547; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
548;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
549;   and set-up of base pointer (x19).
550; CHECK-MACHO: mov	w9, w0
551; CHECK-MACHO: mov	 x10, sp
552; CHECK-MACHO: lsl	x9, x9, #2
553; CHECK-MACHO: add	x9, x9, #15
554; CHECK-MACHO: and	x9, x9, #0x7fffffff0
555; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
556; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
557;   Check correct access to local variable, through base pointer
558; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
559; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
560;   Check epilogue:
561;     Check that stack pointer get restored from frame pointer.
562; CHECK-MACHO: sub	sp, x29, #16
563; CHECK-MACHO: ldp	x29, x30, [sp, #16]
564; CHECK-MACHO: ldp	x20, x19, [sp], #32
565; CHECK-MACHO: ret
566
567
568; Function Attrs: nounwind
569define i32 @vla_dynamicrealign_nocall_large_align(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 {
570entry:
571  %l1 = alloca i32, align 32768
572  %0 = zext i32 %i1 to i64
573  %vla = alloca i32, i64 %0, align 4
574  %conv = fptosi double %d10 to i32
575  %add = add nsw i32 %conv, %i10
576  %l1.0.l1.0. = load volatile i32, i32* %l1, align 32768
577  %add1 = add nsw i32 %add, %l1.0.l1.0.
578  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
579  %add2 = add nsw i32 %add1, %1
580  ret i32 %add2
581}
582
583; CHECK-LABEL: vla_dynamicrealign_nocall_large_align
584;   Check that used callee-saved registers are saved
585; CHECK: stp	x28, x19, [sp, #-32]!
586;   Check that the frame pointer is created:
587; CHECK: stp	x29, x30, [sp, #16]
588; CHECK: add	x29, sp, #16
589;   Check that the stack pointer gets re-aligned to 128
590;   bytes & the base pointer (x19) gets initialized to
591;   this 128-byte aligned area for local variables &
592;   spill slots
593; CHECK: sub	x9, sp, #7, lsl #12
594; CHECK: and	sp, x9, #0xffffffffffff8000
595; CHECK: mov    x19, sp
596;   Check correct access to arguments passed on the stack, through frame pointer
597; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
598; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
599;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
600;   and set-up of base pointer (x19).
601; CHECK: mov	w9, w0
602; CHECK: mov	 x10, sp
603; CHECK: lsl	x9, x9, #2
604; CHECK: add	x9, x9, #15
605; CHECK: and	x9, x9, #0x7fffffff0
606; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
607; CHECK: mov	 sp, x[[VLASPTMP]]
608;   Check correct access to local variable, through base pointer
609; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
610; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
611;   Check epilogue:
612;     Check that stack pointer get restored from frame pointer.
613; CHECK: sub	sp, x29, #16
614; CHECK: ldp	x29, x30, [sp, #16]
615; CHECK: ldp	x28, x19, [sp], #32
616; CHECK: ret
617
618; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall_large_align:
619;   Check that used callee-saved registers are saved
620; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
621;   Check that the frame pointer is created:
622; CHECK-MACHO: stp	x29, x30, [sp, #16]
623; CHECK-MACHO: add	x29, sp, #16
624;   Check that the stack pointer gets re-aligned to 128
625;   bytes & the base pointer (x19) gets initialized to
626;   this 128-byte aligned area for local variables &
627;   spill slots
628; CHECK-MACHO: sub	x9, sp, #7, lsl #12
629; CHECK-MACHO: and	sp, x9, #0xffffffffffff8000
630; CHECK-MACHO: mov    x19, sp
631;   Check correct access to arguments passed on the stack, through frame pointer
632; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
633; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
634;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
635;   and set-up of base pointer (x19).
636; CHECK-MACHO: mov	w9, w0
637; CHECK-MACHO: mov	 x10, sp
638; CHECK-MACHO: lsl	x9, x9, #2
639; CHECK-MACHO: add	x9, x9, #15
640; CHECK-MACHO: and	x9, x9, #0x7fffffff0
641; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
642; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
643;   Check correct access to local variable, through base pointer
644; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
645; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
646;   Check epilogue:
647;     Check that stack pointer get restored from frame pointer.
648; CHECK-MACHO: sub	sp, x29, #16
649; CHECK-MACHO: ldp	x29, x30, [sp, #16]
650; CHECK-MACHO: ldp	x20, x19, [sp], #32
651; CHECK-MACHO: ret
652
653
654define void @realign_conditional(i1 %b) {
655entry:
656  br i1 %b, label %bb0, label %bb1
657
658bb0:
659  %MyAlloca = alloca i8, i64 64, align 32
660  br label %bb1
661
662bb1:
663  ret void
664}
665
666; CHECK-LABEL: realign_conditional
667; No realignment in the prologue.
668; CHECK-NOT:  and
669; CHECK-NOT:  0xffffffffffffffe0
670; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
671; Stack is realigned in a non-entry BB.
672; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
673; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
674; CHECK:  .[[LABEL]]:
675; CHECK:  ret
676
677
678define void @realign_conditional2(i1 %b) {
679entry:
680  %tmp = alloca i8, i32 4
681  br i1 %b, label %bb0, label %bb1
682
683bb0:
684  %MyAlloca = alloca i8, i64 64, align 32
685  br label %bb1
686
687bb1:
688  ret void
689}
690
691; CHECK-LABEL: realign_conditional2
692; Extra realignment in the prologue (performance issue).
693; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
694; CHECK:  sub  x9, sp, #32            // =32
695; CHECK:  and  sp, x9, #0xffffffffffffffe0
696; CHECK:  mov   x19, sp
697; Stack is realigned in a non-entry BB.
698; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
699; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
700; CHECK:  .[[LABEL]]:
701; CHECK:  ret
702
703attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
704attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
705
706!1 = !{!2, !2, i64 0}
707!2 = !{!"int", !3, i64 0}
708!3 = !{!"omnipotent char", !4, i64 0}
709!4 = !{!"Simple C/C++ TBAA"}
710