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 -frame-pointer=all -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: sub	sp, sp, #32
102; CHECK: .cfi_def_cfa_offset 32
103; CHECK: stp	x30, x19, [sp, #16]
104;   Check correctness of cfi pseudo-instructions
105; CHECK: .cfi_offset w19, -8
106; CHECK: .cfi_offset w30, -16
107;   Check correct access to arguments passed on the stack, through stack pointer
108; CHECK: ldr	d[[DARG:[0-9]+]], [sp, #56]
109; CHECK: ldr	w[[IARG:[0-9]+]], [sp, #40]
110;   Check correct access to local variable on the stack, through stack pointer
111; CHECK: ldr	w[[ILOC:[0-9]+]], [sp, #12]
112;   Check epilogue:
113; CHECK: ldp	x30, x19, [sp, #16]
114; CHECK: ret
115; CHECK: .cfi_endproc
116
117; CHECK-MACHO-LABEL: _novla_nodynamicrealign_call:
118; CHECK-MACHO: .cfi_startproc
119;   Check that used callee-saved registers are saved
120; CHECK-MACHO: sub	sp, sp, #48
121; CHECK-MACHO:.cfi_def_cfa_offset 48
122; CHECK-MACHO: stp	x20, x19, [sp, #16]
123;   Check that the frame pointer is created:
124; CHECK-MACHO: stp	x29, x30, [sp, #32]
125; CHECK-MACHO: add	x29, sp, #32
126;   Check correctness of cfi pseudo-instructions
127; CHECK-MACHO: .cfi_def_cfa w29, 16
128; CHECK-MACHO: .cfi_offset w30, -8
129; CHECK-MACHO: .cfi_offset w29, -16
130; CHECK-MACHO: .cfi_offset w19, -24
131; CHECK-MACHO: .cfi_offset w20, -32
132;   Check correct access to arguments passed on the stack, through frame pointer
133; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
134; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
135;   Check correct access to local variable on the stack, through stack pointer
136; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [sp, #12]
137;   Check epilogue:
138; CHECK-MACHO: ldp	x29, x30, [sp, #32]
139; CHECK-MACHO: ldp	x20, x19, [sp, #16]
140; CHECK-MACHO: ret
141; CHECK-MACHO: .cfi_endproc
142
143
144declare i32 @g() #0
145
146; Function Attrs: nounwind
147define 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 {
148entry:
149  %l1 = alloca i32, align 4
150  %conv = fptosi double %d10 to i32
151  %add = add nsw i32 %conv, %i10
152  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
153  %add1 = add nsw i32 %add, %l1.0.l1.0.
154  ret i32 %add1
155}
156; CHECK-LABEL: novla_nodynamicrealign_nocall
157;   Check that space is reserved for one local variable on the stack.
158; CHECK:	sub	sp, sp, #16
159;   Check correct access to arguments passed on the stack, through stack pointer
160; CHECK: ldr	d[[DARG:[0-9]+]], [sp, #40]
161; CHECK: ldr	w[[IARG:[0-9]+]], [sp, #24]
162;   Check correct access to local variable on the stack, through stack pointer
163; CHECK: ldr	w[[ILOC:[0-9]+]], [sp, #12]
164;   Check epilogue:
165; CHECK: add	sp, sp, #16
166; CHECK: ret
167
168
169define 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 {
170entry:
171  %l1 = alloca i32, align 128
172  %conv = fptosi double %d10 to i32
173  %add = add nsw i32 %conv, %i10
174  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
175  %add1 = add nsw i32 %add, %l1.0.l1.0.
176  %call = tail call i32 @g()
177  %add2 = add nsw i32 %add1, %call
178  ret i32 %add2
179}
180
181; CHECK-LABEL: novla_dynamicrealign_call
182; CHECK: .cfi_startproc
183;   Check that used callee-saved registers are saved
184; CHECK: stp	x29, x30, [sp, #-32]!
185; CHECK: .cfi_def_cfa_offset 32
186;   Check that the frame pointer is created:
187; CHECK: str	x19, [sp, #16]
188; CHECK: mov	x29, sp
189;   Check correctness of cfi pseudo-instructions
190; CHECK: .cfi_def_cfa w29, 32
191; CHECK: .cfi_offset w19, -16
192; CHECK: .cfi_offset w30, -24
193; CHECK: .cfi_offset w29, -32
194;   Check the dynamic realignment of the stack pointer to a 128-byte boundary
195; CHECK: sub	x9, sp, #96
196; CHECK: and	sp, x9, #0xffffffffffffff80
197;   Check correct access to arguments passed on the stack, through frame pointer
198; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #56]
199; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #40]
200;   Check correct access to local variable on the stack, through re-aligned stack pointer
201; CHECK: ldr	w[[ILOC:[0-9]+]], [sp]
202;   Check epilogue:
203;     Check that stack pointer get restored from frame pointer.
204; CHECK: mov	sp, x29
205; CHECK: ldr	x19, [sp, #16]
206; CHECK: ldp	x29, x30, [sp], #32
207; CHECK: ret
208; CHECK: .cfi_endproc
209
210; CHECK-MACHO-LABEL: _novla_dynamicrealign_call:
211; CHECK-MACHO: .cfi_startproc
212;   Check that used callee-saved registers are saved
213; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
214; CHECK-MACHO: .cfi_def_cfa_offset 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 correctness of cfi pseudo-instructions
219; CHECK-MACHO: .cfi_def_cfa w29, 16
220; CHECK-MACHO: .cfi_offset w30, -8
221; CHECK-MACHO: .cfi_offset w29, -16
222; CHECK-MACHO: .cfi_offset w19, -24
223; CHECK-MACHO: .cfi_offset w20, -32
224;   Check the dynamic realignment of the stack pointer to a 128-byte boundary
225; CHECK-MACHO: sub	x9, sp, #96
226; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
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	x29, x30, [sp, #-32]!
291; CHECK: .cfi_def_cfa_offset 32
292;   Check that the frame pointer is created:
293; CHECK: stp	x20, x19, [sp, #16]
294; CHECK: mov	x29, sp
295;   Check correctness of cfi pseudo-instructions
296; CHECK: .cfi_def_cfa w29, 32
297; CHECK: .cfi_offset w19, -8
298; CHECK: .cfi_offset w20, -16
299; CHECK: .cfi_offset w30, -24
300; CHECK: .cfi_offset w29, -32
301;   Check that space is reserved on the stack for the local variable,
302;   rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
303; CHECK: sub	sp, sp, #16
304;   Check correct access to arguments passed on the stack, through frame pointer
305; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #40]
306; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #56]
307;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
308; CHECK: mov	w9, w0
309; CHECK: mov	 x10, sp
310; CHECK: lsl	x9, x9, #2
311; CHECK: add	x9, x9, #15
312; CHECK: and	x9, x9, #0x7fffffff0
313; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
314; CHECK: mov	 sp, x[[VLASPTMP]]
315;   Check correct access to local variable, through frame pointer
316; CHECK: ldur	w[[ILOC:[0-9]+]], [x29, #-4]
317;   Check correct accessing of the VLA variable through the base pointer
318; CHECK: ldr	w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
319;   Check epilogue:
320;     Check that stack pointer get restored from frame pointer.
321; CHECK: mov	sp, x29
322; CHECK: ldp	x20, x19, [sp, #16]
323; CHECK: ldp	x29, x30, [sp], #32
324; CHECK: ret
325; CHECK: .cfi_endproc
326
327
328; Function Attrs: nounwind
329define 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 {
330entry:
331  %l1 = alloca i32, align 4
332  %0 = zext i32 %i1 to i64
333  %vla = alloca i32, i64 %0, align 4
334  %conv = fptosi double %d10 to i32
335  %add = add nsw i32 %conv, %i10
336  %l1.0.l1.0. = load volatile i32, i32* %l1, align 4
337  %add1 = add nsw i32 %add, %l1.0.l1.0.
338  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
339  %add2 = add nsw i32 %add1, %1
340  ret i32 %add2
341}
342
343; CHECK-LABEL: vla_nodynamicrealign_nocall
344;   Check that the frame pointer is created:
345; CHECK: stp	x29, x30, [sp, #-16]!
346; CHECK: mov	x29, sp
347;   Check that space is reserved on the stack for the local variable,
348;   rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
349; CHECK: sub	sp, sp, #16
350;   Check correctness of cfi pseudo-instructions
351;   Check correct access to arguments passed on the stack, through frame pointer
352; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #24]
353; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #40]
354;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
355; CHECK: mov	w9, w0
356; CHECK: mov	 x10, sp
357; CHECK: lsl	x9, x9, #2
358; CHECK: add	x9, x9, #15
359; CHECK: and	x9, x9, #0x7fffffff0
360; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
361; CHECK: mov	 sp, x[[VLASPTMP]]
362;   Check correct access to local variable, through frame pointer
363; CHECK: ldur	w[[ILOC:[0-9]+]], [x29, #-4]
364;   Check correct accessing of the VLA variable through the base pointer
365; CHECK: ldr	w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
366;   Check epilogue:
367;     Check that stack pointer get restored from frame pointer.
368; CHECK: mov    sp, x29
369; CHECK: ldp	x29, x30, [sp], #16
370; CHECK: ret
371
372
373define 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 {
374entry:
375  %l1 = alloca i32, align 128
376  %0 = zext i32 %i1 to i64
377  %vla = alloca i32, i64 %0, align 4
378  %conv = fptosi double %d10 to i32
379  %add = add nsw i32 %conv, %i10
380  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
381  %add1 = add nsw i32 %add, %l1.0.l1.0.
382  %call = tail call i32 @g()
383  %add2 = add nsw i32 %add1, %call
384  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
385  %add3 = add nsw i32 %add2, %1
386  ret i32 %add3
387}
388
389; CHECK-LABEL: vla_dynamicrealign_call
390; CHECK: .cfi_startproc
391;   Check that used callee-saved registers are saved
392; CHECK: stp	x29, x30, [sp, #-48]!
393; CHECK: .cfi_def_cfa_offset 48
394; CHECK: str	x21, [sp, #16]
395; CHECK: stp	x20, x19, [sp, #32]
396;   Check that the frame pointer is created:
397; CHECK: mov	x29, sp
398;   Check correctness of cfi pseudo-instructions
399; CHECK: .cfi_def_cfa w29, 48
400; CHECK: .cfi_offset w19, -8
401; CHECK: .cfi_offset w20, -16
402; CHECK: .cfi_offset w21, -32
403; CHECK: .cfi_offset w30, -40
404; CHECK: .cfi_offset w29, -48
405;   Check that the stack pointer gets re-aligned to 128
406;   bytes & the base pointer (x19) gets initialized to
407;   this 128-byte aligned area for local variables &
408;   spill slots
409; CHECK: sub	x9, sp, #80
410; CHECK: and	sp, x9, #0xffffffffffffff80
411; CHECK: mov    x19, sp
412;   Check correct access to arguments passed on the stack, through frame pointer
413; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #56]
414; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #72]
415;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
416;   and set-up of base pointer (x19).
417; CHECK: mov	w9, w0
418; CHECK: mov	 x10, sp
419; CHECK: lsl	x9, x9, #2
420; CHECK: add	x9, x9, #15
421; CHECK: and	x9, x9, #0x7fffffff0
422; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
423; CHECK: mov	 sp, x[[VLASPTMP]]
424;   Check correct access to local variable, through base pointer
425; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
426; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
427;   Check epilogue:
428;     Check that stack pointer get restored from frame pointer.
429; CHECK: mov	sp, x29
430; CHECK: ldp	x20, x19, [sp, #32]
431; CHECK: ldr	x21, [sp, #16]
432; CHECK: ldp	x29, x30, [sp], #48
433; CHECK: ret
434; CHECK: .cfi_endproc
435
436; CHECK-MACHO-LABEL: _vla_dynamicrealign_call:
437; CHECK-MACHO: .cfi_startproc
438;   Check that used callee-saved registers are saved
439; CHECK-MACHO: stp	x22, x21, [sp, #-48]!
440; CHECK-MACHO: .cfi_def_cfa_offset 48
441; CHECK-MACHO: stp	x20, x19, [sp, #16]
442;   Check that the frame pointer is created:
443; CHECK-MACHO: stp	x29, x30, [sp, #32]
444; CHECK-MACHO: add	x29, sp, #32
445;   Check correctness of cfi pseudo-instructions
446; CHECK-MACHO: .cfi_def_cfa w29, 16
447; CHECK-MACHO: .cfi_offset w30, -8
448; CHECK-MACHO: .cfi_offset w29, -16
449; CHECK-MACHO: .cfi_offset w19, -24
450; CHECK-MACHO: .cfi_offset w20, -32
451; CHECK-MACHO: .cfi_offset w21, -40
452; CHECK-MACHO: .cfi_offset w22, -48
453;   Check that the stack pointer gets re-aligned to 128
454;   bytes & the base pointer (x19) gets initialized to
455;   this 128-byte aligned area for local variables &
456;   spill slots
457; CHECK-MACHO: sub	x9, sp, #80
458; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
459; CHECK-MACHO: mov    x19, sp
460;   Check correct access to arguments passed on the stack, through frame pointer
461; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
462; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
463;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
464;   and set-up of base pointer (x19).
465; CHECK-MACHO: mov	w9, w0
466; CHECK-MACHO: mov	 x10, sp
467; CHECK-MACHO: lsl	x9, x9, #2
468; CHECK-MACHO: add	x9, x9, #15
469; CHECK-MACHO: and	x9, x9, #0x7fffffff0
470; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
471; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
472;   Check correct access to local variable, through base pointer
473; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
474; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
475;   Check epilogue:
476;     Check that stack pointer get restored from frame pointer.
477; CHECK-MACHO: sub	sp, x29, #32
478; CHECK-MACHO: ldp	x29, x30, [sp, #32]
479; CHECK-MACHO: ldp	x20, x19, [sp, #16]
480; CHECK-MACHO: ldp	x22, x21, [sp], #48
481; CHECK-MACHO: ret
482; CHECK-MACHO: .cfi_endproc
483
484
485; Function Attrs: nounwind
486define 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 {
487entry:
488  %l1 = alloca i32, align 128
489  %0 = zext i32 %i1 to i64
490  %vla = alloca i32, i64 %0, align 4
491  %conv = fptosi double %d10 to i32
492  %add = add nsw i32 %conv, %i10
493  %l1.0.l1.0. = load volatile i32, i32* %l1, align 128
494  %add1 = add nsw i32 %add, %l1.0.l1.0.
495  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
496  %add2 = add nsw i32 %add1, %1
497  ret i32 %add2
498}
499
500; CHECK-LABEL: vla_dynamicrealign_nocall
501;   Check that used callee-saved registers are saved
502; CHECK: stp	x29, x30, [sp, #-32]!
503; CHECK: str	x19, [sp, #16]
504;   Check that the frame pointer is created:
505; CHECK: mov	x29, sp
506;   Check that the stack pointer gets re-aligned to 128
507;   bytes & the base pointer (x19) gets initialized to
508;   this 128-byte aligned area for local variables &
509;   spill slots
510; CHECK: sub	x9, sp, #96
511; CHECK: and	sp, x9, #0xffffffffffffff80
512; CHECK: mov    x19, sp
513;   Check correct access to arguments passed on the stack, through frame pointer
514; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #40]
515; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #56]
516;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
517;   and set-up of base pointer (x19).
518; CHECK: mov	w9, w0
519; CHECK: mov	 x10, sp
520; CHECK: lsl	x9, x9, #2
521; CHECK: add	x9, x9, #15
522; CHECK: and	x9, x9, #0x7fffffff0
523; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
524; CHECK: mov	 sp, x[[VLASPTMP]]
525;   Check correct access to local variable, through base pointer
526; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
527; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
528;   Check epilogue:
529;     Check that stack pointer get restored from frame pointer.
530; CHECK: mov	sp, x29
531; CHECK: ldr	x19, [sp, #16]
532; CHECK: ldp	x29, x30, [sp], #32
533; CHECK: ret
534
535; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall:
536;   Check that used callee-saved registers are saved
537; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
538;   Check that the frame pointer is created:
539; CHECK-MACHO: stp	x29, x30, [sp, #16]
540; CHECK-MACHO: add	x29, sp, #16
541;   Check that the stack pointer gets re-aligned to 128
542;   bytes & the base pointer (x19) gets initialized to
543;   this 128-byte aligned area for local variables &
544;   spill slots
545; CHECK-MACHO: sub	x9, sp, #96
546; CHECK-MACHO: and	sp, x9, #0xffffffffffffff80
547; CHECK-MACHO: mov    x19, sp
548;   Check correct access to arguments passed on the stack, through frame pointer
549; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
550; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
551;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
552;   and set-up of base pointer (x19).
553; CHECK-MACHO: mov	w9, w0
554; CHECK-MACHO: mov	 x10, sp
555; CHECK-MACHO: lsl	x9, x9, #2
556; CHECK-MACHO: add	x9, x9, #15
557; CHECK-MACHO: and	x9, x9, #0x7fffffff0
558; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
559; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
560;   Check correct access to local variable, through base pointer
561; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
562; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
563;   Check epilogue:
564;     Check that stack pointer get restored from frame pointer.
565; CHECK-MACHO: sub	sp, x29, #16
566; CHECK-MACHO: ldp	x29, x30, [sp, #16]
567; CHECK-MACHO: ldp	x20, x19, [sp], #32
568; CHECK-MACHO: ret
569
570
571; Function Attrs: nounwind
572define 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 {
573entry:
574  %l1 = alloca i32, align 32768
575  %0 = zext i32 %i1 to i64
576  %vla = alloca i32, i64 %0, align 4
577  %conv = fptosi double %d10 to i32
578  %add = add nsw i32 %conv, %i10
579  %l1.0.l1.0. = load volatile i32, i32* %l1, align 32768
580  %add1 = add nsw i32 %add, %l1.0.l1.0.
581  %1 = load volatile i32, i32* %vla, align 4, !tbaa !1
582  %add2 = add nsw i32 %add1, %1
583  ret i32 %add2
584}
585
586; CHECK-LABEL: vla_dynamicrealign_nocall_large_align
587;   Check that used callee-saved registers are saved
588; CHECK: stp	x29, x30, [sp, #-32]!
589; CHECK: str  x19, [sp, #16]
590;   Check that the frame pointer is created:
591; CHECK: mov	x29, sp
592;   Check that the stack pointer gets re-aligned to 128
593;   bytes & the base pointer (x19) gets initialized to
594;   this 128-byte aligned area for local variables &
595;   spill slots
596; CHECK: sub	x9, sp, #7, lsl #12
597; CHECK: and	sp, x9, #0xffffffffffff8000
598; CHECK: mov    x19, sp
599;   Check correct access to arguments passed on the stack, through frame pointer
600; CHECK: ldr	w[[IARG:[0-9]+]], [x29, #40]
601; CHECK: ldr	d[[DARG:[0-9]+]], [x29, #56]
602;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
603;   and set-up of base pointer (x19).
604; CHECK: mov	w9, w0
605; CHECK: mov	 x10, sp
606; CHECK: lsl	x9, x9, #2
607; CHECK: add	x9, x9, #15
608; CHECK: and	x9, x9, #0x7fffffff0
609; CHECK: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
610; CHECK: mov	 sp, x[[VLASPTMP]]
611;   Check correct access to local variable, through base pointer
612; CHECK: ldr	w[[ILOC:[0-9]+]], [x19]
613; CHECK: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
614;   Check epilogue:
615;     Check that stack pointer get restored from frame pointer.
616; CHECK: mov	sp, x29
617; CHECK: ldr  x19, [sp, #16]
618; CHECK: ldp	x29, x30, [sp], #32
619; CHECK: ret
620
621; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall_large_align:
622;   Check that used callee-saved registers are saved
623; CHECK-MACHO: stp	x20, x19, [sp, #-32]!
624;   Check that the frame pointer is created:
625; CHECK-MACHO: stp	x29, x30, [sp, #16]
626; CHECK-MACHO: add	x29, sp, #16
627;   Check that the stack pointer gets re-aligned to 128
628;   bytes & the base pointer (x19) gets initialized to
629;   this 128-byte aligned area for local variables &
630;   spill slots
631; CHECK-MACHO: sub	x9, sp, #7, lsl #12
632; CHECK-MACHO: and	sp, x9, #0xffffffffffff8000
633; CHECK-MACHO: mov    x19, sp
634;   Check correct access to arguments passed on the stack, through frame pointer
635; CHECK-MACHO: ldr	w[[IARG:[0-9]+]], [x29, #20]
636; CHECK-MACHO: ldr	d[[DARG:[0-9]+]], [x29, #32]
637;   Check correct reservation of 16-byte aligned VLA (size in w0) on stack
638;   and set-up of base pointer (x19).
639; CHECK-MACHO: mov	w9, w0
640; CHECK-MACHO: mov	 x10, sp
641; CHECK-MACHO: lsl	x9, x9, #2
642; CHECK-MACHO: add	x9, x9, #15
643; CHECK-MACHO: and	x9, x9, #0x7fffffff0
644; CHECK-MACHO: sub	 x[[VLASPTMP:[0-9]+]], x10, x9
645; CHECK-MACHO: mov	 sp, x[[VLASPTMP]]
646;   Check correct access to local variable, through base pointer
647; CHECK-MACHO: ldr	w[[ILOC:[0-9]+]], [x19]
648; CHECK-MACHO: ldr	 w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
649;   Check epilogue:
650;     Check that stack pointer get restored from frame pointer.
651; CHECK-MACHO: sub	sp, x29, #16
652; CHECK-MACHO: ldp	x29, x30, [sp, #16]
653; CHECK-MACHO: ldp	x20, x19, [sp], #32
654; CHECK-MACHO: ret
655
656
657define void @realign_conditional(i1 %b) {
658entry:
659  br i1 %b, label %bb0, label %bb1
660
661bb0:
662  %MyAlloca = alloca i8, i64 64, align 32
663  br label %bb1
664
665bb1:
666  ret void
667}
668
669; CHECK-LABEL: realign_conditional
670; No realignment in the prologue.
671; CHECK-NOT:  and
672; CHECK-NOT:  0xffffffffffffffe0
673; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
674; Stack is realigned in a non-entry BB.
675; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
676; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
677; CHECK:  .[[LABEL]]:
678; CHECK:  ret
679
680
681define void @realign_conditional2(i1 %b) {
682entry:
683  %tmp = alloca i8, i32 16
684  br i1 %b, label %bb0, label %bb1
685
686bb0:
687  %MyAlloca = alloca i8, i64 64, align 32
688  br label %bb1
689
690bb1:
691  ret void
692}
693
694; CHECK-LABEL: realign_conditional2
695; Extra realignment in the prologue (performance issue).
696; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
697; CHECK:  sub  x9, sp, #32
698; CHECK:  and  sp, x9, #0xffffffffffffffe0
699; CHECK:  mov   x19, sp
700; Stack is realigned in a non-entry BB.
701; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
702; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
703; CHECK:  .[[LABEL]]:
704; CHECK:  ret
705
706attributes #0 = { "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
707attributes #1 = { nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
708
709!1 = !{!2, !2, i64 0}
710!2 = !{!"int", !3, i64 0}
711!3 = !{!"omnipotent char", !4, i64 0}
712!4 = !{!"Simple C/C++ TBAA"}
713