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