1; RUN: llc < %s -mtriple=arm64-apple-ios7.0.0 -mcpu=cyclone -enable-misched=false | FileCheck %s
2
3; rdar://13625505
4; Here we have 9 fixed integer arguments the 9th argument in on stack, the
5; varargs start right after at 8-byte alignment.
6define void @fn9(i32* %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9, ...) nounwind noinline ssp {
7; CHECK-LABEL: fn9:
8; 9th fixed argument
9; CHECK: ldr {{w[0-9]+}}, [sp, #64]
10; CHECK: add [[ARGS:x[0-9]+]], sp, #72
11; CHECK: add {{x[0-9]+}}, [[ARGS]], #8
12; First vararg
13; CHECK: ldr {{w[0-9]+}}, [sp, #72]
14; Second vararg
15; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}], #8
16; Third vararg
17; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}], #8
18  %1 = alloca i32, align 4
19  %2 = alloca i32, align 4
20  %3 = alloca i32, align 4
21  %4 = alloca i32, align 4
22  %5 = alloca i32, align 4
23  %6 = alloca i32, align 4
24  %7 = alloca i32, align 4
25  %8 = alloca i32, align 4
26  %9 = alloca i32, align 4
27  %args = alloca i8*, align 8
28  %a10 = alloca i32, align 4
29  %a11 = alloca i32, align 4
30  %a12 = alloca i32, align 4
31  store i32 %a2, i32* %2, align 4
32  store i32 %a3, i32* %3, align 4
33  store i32 %a4, i32* %4, align 4
34  store i32 %a5, i32* %5, align 4
35  store i32 %a6, i32* %6, align 4
36  store i32 %a7, i32* %7, align 4
37  store i32 %a8, i32* %8, align 4
38  store i32 %a9, i32* %9, align 4
39  store i32 %a9, i32* %a1
40  %10 = bitcast i8** %args to i8*
41  call void @llvm.va_start(i8* %10)
42  %11 = va_arg i8** %args, i32
43  store i32 %11, i32* %a10, align 4
44  %12 = va_arg i8** %args, i32
45  store i32 %12, i32* %a11, align 4
46  %13 = va_arg i8** %args, i32
47  store i32 %13, i32* %a12, align 4
48  ret void
49}
50
51declare void @llvm.va_start(i8*) nounwind
52
53define i32 @main() nounwind ssp {
54; CHECK-LABEL: main:
55; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]
56; CHECK: str {{x[0-9]+}}, [sp, #8]
57; CHECK: str {{w[0-9]+}}, [sp]
58  %a1 = alloca i32, align 4
59  %a2 = alloca i32, align 4
60  %a3 = alloca i32, align 4
61  %a4 = alloca i32, align 4
62  %a5 = alloca i32, align 4
63  %a6 = alloca i32, align 4
64  %a7 = alloca i32, align 4
65  %a8 = alloca i32, align 4
66  %a9 = alloca i32, align 4
67  %a10 = alloca i32, align 4
68  %a11 = alloca i32, align 4
69  %a12 = alloca i32, align 4
70  store i32 1, i32* %a1, align 4
71  store i32 2, i32* %a2, align 4
72  store i32 3, i32* %a3, align 4
73  store i32 4, i32* %a4, align 4
74  store i32 5, i32* %a5, align 4
75  store i32 6, i32* %a6, align 4
76  store i32 7, i32* %a7, align 4
77  store i32 8, i32* %a8, align 4
78  store i32 9, i32* %a9, align 4
79  store i32 10, i32* %a10, align 4
80  store i32 11, i32* %a11, align 4
81  store i32 12, i32* %a12, align 4
82  %1 = load i32, i32* %a1, align 4
83  %2 = load i32, i32* %a2, align 4
84  %3 = load i32, i32* %a3, align 4
85  %4 = load i32, i32* %a4, align 4
86  %5 = load i32, i32* %a5, align 4
87  %6 = load i32, i32* %a6, align 4
88  %7 = load i32, i32* %a7, align 4
89  %8 = load i32, i32* %a8, align 4
90  %9 = load i32, i32* %a9, align 4
91  %10 = load i32, i32* %a10, align 4
92  %11 = load i32, i32* %a11, align 4
93  %12 = load i32, i32* %a12, align 4
94  call void (i32*, i32, i32, i32, i32, i32, i32, i32, i32, ...) @fn9(i32* %a1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12)
95  ret i32 0
96}
97
98;rdar://13668483
99@.str = private unnamed_addr constant [4 x i8] c"fmt\00", align 1
100define void @foo(i8* %fmt, ...) nounwind {
101entry:
102; CHECK-LABEL: foo:
103; CHECK: ldr {{w[0-9]+}}, [sp, #48]
104; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #23
105; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
106; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]]
107  %fmt.addr = alloca i8*, align 8
108  %args = alloca i8*, align 8
109  %vc = alloca i32, align 4
110  %vv = alloca <4 x i32>, align 16
111  store i8* %fmt, i8** %fmt.addr, align 8
112  %args1 = bitcast i8** %args to i8*
113  call void @llvm.va_start(i8* %args1)
114  %0 = va_arg i8** %args, i32
115  store i32 %0, i32* %vc, align 4
116  %1 = va_arg i8** %args, <4 x i32>
117  store <4 x i32> %1, <4 x i32>* %vv, align 16
118  ret void
119}
120
121define void @bar(i32 %x, <4 x i32> %y) nounwind {
122entry:
123; CHECK-LABEL: bar:
124; CHECK: stp {{q[0-9]+}}, {{q[0-9]+}}, [sp, #16]
125; CHECK: str {{x[0-9]+}}, [sp]
126  %x.addr = alloca i32, align 4
127  %y.addr = alloca <4 x i32>, align 16
128  store i32 %x, i32* %x.addr, align 4
129  store <4 x i32> %y, <4 x i32>* %y.addr, align 16
130  %0 = load i32, i32* %x.addr, align 4
131  %1 = load <4 x i32>, <4 x i32>* %y.addr, align 16
132  call void (i8*, ...) @foo(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0, <4 x i32> %1)
133  ret void
134}
135
136; rdar://13668927
137; When passing 16-byte aligned small structs as vararg, make sure the caller
138; side is 16-byte aligned on stack.
139%struct.s41 = type { i32, i16, i32, i16 }
140define void @foo2(i8* %fmt, ...) nounwind {
141entry:
142; CHECK-LABEL: foo2:
143; CHECK: ldr {{w[0-9]+}}, [sp, #48]
144; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #23
145; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
146; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]]
147  %fmt.addr = alloca i8*, align 8
148  %args = alloca i8*, align 8
149  %vc = alloca i32, align 4
150  %vs = alloca %struct.s41, align 16
151  store i8* %fmt, i8** %fmt.addr, align 8
152  %args1 = bitcast i8** %args to i8*
153  call void @llvm.va_start(i8* %args1)
154  %0 = va_arg i8** %args, i32
155  store i32 %0, i32* %vc, align 4
156  %ap.cur = load i8*, i8** %args
157  %1 = getelementptr i8, i8* %ap.cur, i32 15
158  %2 = ptrtoint i8* %1 to i64
159  %3 = and i64 %2, -16
160  %ap.align = inttoptr i64 %3 to i8*
161  %ap.next = getelementptr i8, i8* %ap.align, i32 16
162  store i8* %ap.next, i8** %args
163  %4 = bitcast i8* %ap.align to %struct.s41*
164  %5 = bitcast %struct.s41* %vs to i8*
165  %6 = bitcast %struct.s41* %4 to i8*
166  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %5, i8* align 16 %6, i64 16, i1 false)
167  ret void
168}
169declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
170
171define void @bar2(i32 %x, i128 %s41.coerce) nounwind {
172entry:
173; CHECK-LABEL: bar2:
174; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]
175; CHECK: str {{x[0-9]+}}, [sp]
176  %x.addr = alloca i32, align 4
177  %s41 = alloca %struct.s41, align 16
178  store i32 %x, i32* %x.addr, align 4
179  %0 = bitcast %struct.s41* %s41 to i128*
180  store i128 %s41.coerce, i128* %0, align 1
181  %1 = load i32, i32* %x.addr, align 4
182  %2 = bitcast %struct.s41* %s41 to i128*
183  %3 = load i128, i128* %2, align 1
184  call void (i8*, ...) @foo2(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1, i128 %3)
185  ret void
186}
187