1*67e74705SXin Li // RUN: %clang_cc1 -triple arm64-apple-ios7 -target-feature +neon -target-abi darwinpcs -ffreestanding -emit-llvm -w -o - %s | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li // CHECK: define signext i8 @f0()
f0(void)4*67e74705SXin Li char f0(void) {
5*67e74705SXin Li return 0;
6*67e74705SXin Li }
7*67e74705SXin Li
8*67e74705SXin Li // Struct as return type. Aggregates <= 16 bytes are passed directly and round
9*67e74705SXin Li // up to multiple of 8 bytes.
10*67e74705SXin Li // CHECK: define i64 @f1()
11*67e74705SXin Li struct s1 { char f0; };
f1(void)12*67e74705SXin Li struct s1 f1(void) {}
13*67e74705SXin Li
14*67e74705SXin Li // CHECK: define i64 @f2()
15*67e74705SXin Li struct s2 { short f0; };
f2(void)16*67e74705SXin Li struct s2 f2(void) {}
17*67e74705SXin Li
18*67e74705SXin Li // CHECK: define i64 @f3()
19*67e74705SXin Li struct s3 { int f0; };
f3(void)20*67e74705SXin Li struct s3 f3(void) {}
21*67e74705SXin Li
22*67e74705SXin Li // CHECK: define i64 @f4()
23*67e74705SXin Li struct s4 { struct s4_0 { int f0; } f0; };
f4(void)24*67e74705SXin Li struct s4 f4(void) {}
25*67e74705SXin Li
26*67e74705SXin Li // CHECK: define i64 @f5()
27*67e74705SXin Li struct s5 { struct { } f0; int f1; };
f5(void)28*67e74705SXin Li struct s5 f5(void) {}
29*67e74705SXin Li
30*67e74705SXin Li // CHECK: define i64 @f6()
31*67e74705SXin Li struct s6 { int f0[1]; };
f6(void)32*67e74705SXin Li struct s6 f6(void) {}
33*67e74705SXin Li
34*67e74705SXin Li // CHECK: define void @f7()
35*67e74705SXin Li struct s7 { struct { int : 0; } f0; };
f7(void)36*67e74705SXin Li struct s7 f7(void) {}
37*67e74705SXin Li
38*67e74705SXin Li // CHECK: define void @f8()
39*67e74705SXin Li struct s8 { struct { int : 0; } f0[1]; };
f8(void)40*67e74705SXin Li struct s8 f8(void) {}
41*67e74705SXin Li
42*67e74705SXin Li // CHECK: define i64 @f9()
43*67e74705SXin Li struct s9 { int f0; int : 0; };
f9(void)44*67e74705SXin Li struct s9 f9(void) {}
45*67e74705SXin Li
46*67e74705SXin Li // CHECK: define i64 @f10()
47*67e74705SXin Li struct s10 { int f0; int : 0; int : 0; };
f10(void)48*67e74705SXin Li struct s10 f10(void) {}
49*67e74705SXin Li
50*67e74705SXin Li // CHECK: define i64 @f11()
51*67e74705SXin Li struct s11 { int : 0; int f0; };
f11(void)52*67e74705SXin Li struct s11 f11(void) {}
53*67e74705SXin Li
54*67e74705SXin Li // CHECK: define i64 @f12()
55*67e74705SXin Li union u12 { char f0; short f1; int f2; };
f12(void)56*67e74705SXin Li union u12 f12(void) {}
57*67e74705SXin Li
58*67e74705SXin Li // Homogeneous Aggregate as return type will be passed directly.
59*67e74705SXin Li // CHECK: define %struct.s13 @f13()
60*67e74705SXin Li struct s13 { float f0; };
f13(void)61*67e74705SXin Li struct s13 f13(void) {}
62*67e74705SXin Li // CHECK: define %union.u14 @f14()
63*67e74705SXin Li union u14 { float f0; };
f14(void)64*67e74705SXin Li union u14 f14(void) {}
65*67e74705SXin Li
66*67e74705SXin Li // CHECK: define void @f15()
f15(struct s7 a0)67*67e74705SXin Li void f15(struct s7 a0) {}
68*67e74705SXin Li
69*67e74705SXin Li // CHECK: define void @f16()
f16(struct s8 a0)70*67e74705SXin Li void f16(struct s8 a0) {}
71*67e74705SXin Li
72*67e74705SXin Li // CHECK: define i64 @f17()
73*67e74705SXin Li struct s17 { short f0 : 13; char f1 : 4; };
f17(void)74*67e74705SXin Li struct s17 f17(void) {}
75*67e74705SXin Li
76*67e74705SXin Li // CHECK: define i64 @f18()
77*67e74705SXin Li struct s18 { short f0; char f1 : 4; };
f18(void)78*67e74705SXin Li struct s18 f18(void) {}
79*67e74705SXin Li
80*67e74705SXin Li // CHECK: define i64 @f19()
81*67e74705SXin Li struct s19 { int f0; struct s8 f1; };
f19(void)82*67e74705SXin Li struct s19 f19(void) {}
83*67e74705SXin Li
84*67e74705SXin Li // CHECK: define i64 @f20()
85*67e74705SXin Li struct s20 { struct s8 f1; int f0; };
f20(void)86*67e74705SXin Li struct s20 f20(void) {}
87*67e74705SXin Li
88*67e74705SXin Li // CHECK: define i64 @f21()
89*67e74705SXin Li struct s21 { struct {} f1; int f0 : 4; };
f21(void)90*67e74705SXin Li struct s21 f21(void) {}
91*67e74705SXin Li
92*67e74705SXin Li // CHECK: define i64 @f22()
93*67e74705SXin Li // CHECK: define i64 @f23()
94*67e74705SXin Li // CHECK: define i64 @f24()
95*67e74705SXin Li // CHECK: define [2 x i64] @f25()
96*67e74705SXin Li // CHECK: define { float, float } @f26()
97*67e74705SXin Li // CHECK: define { double, double } @f27()
f22(void)98*67e74705SXin Li _Complex char f22(void) {}
f23(void)99*67e74705SXin Li _Complex short f23(void) {}
f24(void)100*67e74705SXin Li _Complex int f24(void) {}
f25(void)101*67e74705SXin Li _Complex long long f25(void) {}
f26(void)102*67e74705SXin Li _Complex float f26(void) {}
f27(void)103*67e74705SXin Li _Complex double f27(void) {}
104*67e74705SXin Li
105*67e74705SXin Li // CHECK: define i64 @f28()
106*67e74705SXin Li struct s28 { _Complex char f0; };
f28()107*67e74705SXin Li struct s28 f28() {}
108*67e74705SXin Li
109*67e74705SXin Li // CHECK: define i64 @f29()
110*67e74705SXin Li struct s29 { _Complex short f0; };
f29()111*67e74705SXin Li struct s29 f29() {}
112*67e74705SXin Li
113*67e74705SXin Li // CHECK: define i64 @f30()
114*67e74705SXin Li struct s30 { _Complex int f0; };
f30()115*67e74705SXin Li struct s30 f30() {}
116*67e74705SXin Li
117*67e74705SXin Li struct s31 { char x; };
f31(struct s31 s)118*67e74705SXin Li void f31(struct s31 s) { }
119*67e74705SXin Li // CHECK: define void @f31(i64 %s.coerce)
120*67e74705SXin Li // CHECK: %s = alloca %struct.s31, align 1
121*67e74705SXin Li // CHECK: trunc i64 %s.coerce to i8
122*67e74705SXin Li // CHECK: store i8 %{{.*}},
123*67e74705SXin Li
124*67e74705SXin Li struct s32 { double x; };
f32(struct s32 s)125*67e74705SXin Li void f32(struct s32 s) { }
126*67e74705SXin Li // CHECK: @f32([1 x double] %{{.*}})
127*67e74705SXin Li
128*67e74705SXin Li // A composite type larger than 16 bytes should be passed indirectly.
129*67e74705SXin Li struct s33 { char buf[32*32]; };
f33(struct s33 s)130*67e74705SXin Li void f33(struct s33 s) { }
131*67e74705SXin Li // CHECK: define void @f33(%struct.s33* %s)
132*67e74705SXin Li
133*67e74705SXin Li struct s34 { char c; };
134*67e74705SXin Li void f34(struct s34 s);
g34(struct s34 * s)135*67e74705SXin Li void g34(struct s34 *s) { f34(*s); }
136*67e74705SXin Li // CHECK: @g34(%struct.s34* %s)
137*67e74705SXin Li // CHECK: %[[a:.*]] = load i8, i8* %{{.*}}
138*67e74705SXin Li // CHECK: zext i8 %[[a]] to i64
139*67e74705SXin Li // CHECK: call void @f34(i64 %{{.*}})
140*67e74705SXin Li
141*67e74705SXin Li /*
142*67e74705SXin Li * Check that va_arg accesses stack according to ABI alignment
143*67e74705SXin Li */
t1(int i,...)144*67e74705SXin Li long long t1(int i, ...) {
145*67e74705SXin Li // CHECK: t1
146*67e74705SXin Li __builtin_va_list ap;
147*67e74705SXin Li __builtin_va_start(ap, i);
148*67e74705SXin Li // CHECK-NOT: add i32 %{{.*}} 7
149*67e74705SXin Li // CHECK-NOT: and i32 %{{.*}} -8
150*67e74705SXin Li long long ll = __builtin_va_arg(ap, long long);
151*67e74705SXin Li __builtin_va_end(ap);
152*67e74705SXin Li return ll;
153*67e74705SXin Li }
t2(int i,...)154*67e74705SXin Li double t2(int i, ...) {
155*67e74705SXin Li // CHECK: t2
156*67e74705SXin Li __builtin_va_list ap;
157*67e74705SXin Li __builtin_va_start(ap, i);
158*67e74705SXin Li // CHECK-NOT: add i32 %{{.*}} 7
159*67e74705SXin Li // CHECK-NOT: and i32 %{{.*}} -8
160*67e74705SXin Li double ll = __builtin_va_arg(ap, double);
161*67e74705SXin Li __builtin_va_end(ap);
162*67e74705SXin Li return ll;
163*67e74705SXin Li }
164*67e74705SXin Li
165*67e74705SXin Li #include <arm_neon.h>
166*67e74705SXin Li
167*67e74705SXin Li // Homogeneous Vector Aggregate as return type and argument type.
168*67e74705SXin Li // CHECK: define %struct.int8x16x2_t @f0_0(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
f0_0(int8x16_t a0,int8x16_t a1)169*67e74705SXin Li int8x16x2_t f0_0(int8x16_t a0, int8x16_t a1) {
170*67e74705SXin Li return vzipq_s8(a0, a1);
171*67e74705SXin Li }
172*67e74705SXin Li
173*67e74705SXin Li // Test direct vector passing.
174*67e74705SXin Li typedef float T_float32x2 __attribute__ ((__vector_size__ (8)));
175*67e74705SXin Li typedef float T_float32x4 __attribute__ ((__vector_size__ (16)));
176*67e74705SXin Li typedef float T_float32x8 __attribute__ ((__vector_size__ (32)));
177*67e74705SXin Li typedef float T_float32x16 __attribute__ ((__vector_size__ (64)));
178*67e74705SXin Li
179*67e74705SXin Li // CHECK: define <2 x float> @f1_0(<2 x float> %{{.*}})
f1_0(T_float32x2 a0)180*67e74705SXin Li T_float32x2 f1_0(T_float32x2 a0) { return a0; }
181*67e74705SXin Li // CHECK: define <4 x float> @f1_1(<4 x float> %{{.*}})
f1_1(T_float32x4 a0)182*67e74705SXin Li T_float32x4 f1_1(T_float32x4 a0) { return a0; }
183*67e74705SXin Li // Vector with length bigger than 16-byte is illegal and is passed indirectly.
184*67e74705SXin Li // CHECK: define void @f1_2(<8 x float>* noalias sret %{{.*}}, <8 x float>*)
f1_2(T_float32x8 a0)185*67e74705SXin Li T_float32x8 f1_2(T_float32x8 a0) { return a0; }
186*67e74705SXin Li // CHECK: define void @f1_3(<16 x float>* noalias sret %{{.*}}, <16 x float>*)
f1_3(T_float32x16 a0)187*67e74705SXin Li T_float32x16 f1_3(T_float32x16 a0) { return a0; }
188*67e74705SXin Li
189*67e74705SXin Li // Testing alignment with aggregates: HFA, aggregates with size <= 16 bytes and
190*67e74705SXin Li // aggregates with size > 16 bytes.
191*67e74705SXin Li struct s35
192*67e74705SXin Li {
193*67e74705SXin Li float v[4]; //Testing HFA.
194*67e74705SXin Li } __attribute__((aligned(16)));
195*67e74705SXin Li typedef struct s35 s35_with_align;
196*67e74705SXin Li
197*67e74705SXin Li typedef __attribute__((neon_vector_type(4))) float float32x4_t;
f35(int i,s35_with_align s1,s35_with_align s2)198*67e74705SXin Li float32x4_t f35(int i, s35_with_align s1, s35_with_align s2) {
199*67e74705SXin Li // CHECK: define <4 x float> @f35(i32 %i, [4 x float] %s1.coerce, [4 x float] %s2.coerce)
200*67e74705SXin Li // CHECK: %s1 = alloca %struct.s35, align 16
201*67e74705SXin Li // CHECK: %s2 = alloca %struct.s35, align 16
202*67e74705SXin Li // CHECK: %[[a:.*]] = bitcast %struct.s35* %s1 to <4 x float>*
203*67e74705SXin Li // CHECK: load <4 x float>, <4 x float>* %[[a]], align 16
204*67e74705SXin Li // CHECK: %[[b:.*]] = bitcast %struct.s35* %s2 to <4 x float>*
205*67e74705SXin Li // CHECK: load <4 x float>, <4 x float>* %[[b]], align 16
206*67e74705SXin Li float32x4_t v = vaddq_f32(*(float32x4_t *)&s1,
207*67e74705SXin Li *(float32x4_t *)&s2);
208*67e74705SXin Li return v;
209*67e74705SXin Li }
210*67e74705SXin Li
211*67e74705SXin Li struct s36
212*67e74705SXin Li {
213*67e74705SXin Li int v[4]; //Testing 16-byte aggregate.
214*67e74705SXin Li } __attribute__((aligned(16)));
215*67e74705SXin Li typedef struct s36 s36_with_align;
216*67e74705SXin Li
217*67e74705SXin Li typedef __attribute__((neon_vector_type(4))) int int32x4_t;
f36(int i,s36_with_align s1,s36_with_align s2)218*67e74705SXin Li int32x4_t f36(int i, s36_with_align s1, s36_with_align s2) {
219*67e74705SXin Li // CHECK: define <4 x i32> @f36(i32 %i, i128 %s1.coerce, i128 %s2.coerce)
220*67e74705SXin Li // CHECK: %s1 = alloca %struct.s36, align 16
221*67e74705SXin Li // CHECK: %s2 = alloca %struct.s36, align 16
222*67e74705SXin Li // CHECK: store i128 %s1.coerce, i128* %{{.*}}, align 16
223*67e74705SXin Li // CHECK: store i128 %s2.coerce, i128* %{{.*}}, align 16
224*67e74705SXin Li // CHECK: %[[a:.*]] = bitcast %struct.s36* %s1 to <4 x i32>*
225*67e74705SXin Li // CHECK: load <4 x i32>, <4 x i32>* %[[a]], align 16
226*67e74705SXin Li // CHECK: %[[b:.*]] = bitcast %struct.s36* %s2 to <4 x i32>*
227*67e74705SXin Li // CHECK: load <4 x i32>, <4 x i32>* %[[b]], align 16
228*67e74705SXin Li int32x4_t v = vaddq_s32(*(int32x4_t *)&s1,
229*67e74705SXin Li *(int32x4_t *)&s2);
230*67e74705SXin Li return v;
231*67e74705SXin Li }
232*67e74705SXin Li
233*67e74705SXin Li struct s37
234*67e74705SXin Li {
235*67e74705SXin Li int v[18]; //Testing large aggregate.
236*67e74705SXin Li } __attribute__((aligned(16)));
237*67e74705SXin Li typedef struct s37 s37_with_align;
238*67e74705SXin Li
f37(int i,s37_with_align s1,s37_with_align s2)239*67e74705SXin Li int32x4_t f37(int i, s37_with_align s1, s37_with_align s2) {
240*67e74705SXin Li // CHECK: define <4 x i32> @f37(i32 %i, %struct.s37* %s1, %struct.s37* %s2)
241*67e74705SXin Li // CHECK: %[[a:.*]] = bitcast %struct.s37* %s1 to <4 x i32>*
242*67e74705SXin Li // CHECK: load <4 x i32>, <4 x i32>* %[[a]], align 16
243*67e74705SXin Li // CHECK: %[[b:.*]] = bitcast %struct.s37* %s2 to <4 x i32>*
244*67e74705SXin Li // CHECK: load <4 x i32>, <4 x i32>* %[[b]], align 16
245*67e74705SXin Li int32x4_t v = vaddq_s32(*(int32x4_t *)&s1,
246*67e74705SXin Li *(int32x4_t *)&s2);
247*67e74705SXin Li return v;
248*67e74705SXin Li }
249*67e74705SXin Li s37_with_align g37;
caller37()250*67e74705SXin Li int32x4_t caller37() {
251*67e74705SXin Li // CHECK: caller37
252*67e74705SXin Li // CHECK: %[[a:.*]] = alloca %struct.s37, align 16
253*67e74705SXin Li // CHECK: %[[b:.*]] = alloca %struct.s37, align 16
254*67e74705SXin Li // CHECK: call void @llvm.memcpy
255*67e74705SXin Li // CHECK: call void @llvm.memcpy
256*67e74705SXin Li // CHECK: call <4 x i32> @f37(i32 3, %struct.s37* %[[a]], %struct.s37* %[[b]])
257*67e74705SXin Li return f37(3, g37, g37);
258*67e74705SXin Li }
259*67e74705SXin Li
260*67e74705SXin Li // rdar://problem/12648441
261*67e74705SXin Li // Test passing structs with size < 8, < 16 and > 16
262*67e74705SXin Li // with alignment of 16 and without
263*67e74705SXin Li
264*67e74705SXin Li // structs with size <= 8 bytes, without alignment attribute
265*67e74705SXin Li // passed as i64 regardless of the align attribute
266*67e74705SXin Li struct s38
267*67e74705SXin Li {
268*67e74705SXin Li int i;
269*67e74705SXin Li short s;
270*67e74705SXin Li };
271*67e74705SXin Li typedef struct s38 s38_no_align;
272*67e74705SXin Li // passing structs in registers
273*67e74705SXin Li __attribute__ ((noinline))
f38(int i,s38_no_align s1,s38_no_align s2)274*67e74705SXin Li int f38(int i, s38_no_align s1, s38_no_align s2) {
275*67e74705SXin Li // CHECK: define i32 @f38(i32 %i, i64 %s1.coerce, i64 %s2.coerce)
276*67e74705SXin Li // CHECK: %s1 = alloca %struct.s38, align 4
277*67e74705SXin Li // CHECK: %s2 = alloca %struct.s38, align 4
278*67e74705SXin Li // CHECK: store i64 %s1.coerce, i64* %{{.*}}, align 4
279*67e74705SXin Li // CHECK: store i64 %s2.coerce, i64* %{{.*}}, align 4
280*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s1, i32 0, i32 0
281*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s2, i32 0, i32 0
282*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s1, i32 0, i32 1
283*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s2, i32 0, i32 1
284*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
285*67e74705SXin Li }
286*67e74705SXin Li s38_no_align g38;
287*67e74705SXin Li s38_no_align g38_2;
caller38()288*67e74705SXin Li int caller38() {
289*67e74705SXin Li // CHECK: define i32 @caller38()
290*67e74705SXin Li // CHECK: %[[a:.*]] = load i64, i64* bitcast (%struct.s38* @g38 to i64*), align 4
291*67e74705SXin Li // CHECK: %[[b:.*]] = load i64, i64* bitcast (%struct.s38* @g38_2 to i64*), align 4
292*67e74705SXin Li // CHECK: call i32 @f38(i32 3, i64 %[[a]], i64 %[[b]])
293*67e74705SXin Li return f38(3, g38, g38_2);
294*67e74705SXin Li }
295*67e74705SXin Li // passing structs on stack
296*67e74705SXin Li __attribute__ ((noinline))
f38_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s38_no_align s1,s38_no_align s2)297*67e74705SXin Li int f38_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
298*67e74705SXin Li int i9, s38_no_align s1, s38_no_align s2) {
299*67e74705SXin Li // CHECK: define i32 @f38_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i64 %s1.coerce, i64 %s2.coerce)
300*67e74705SXin Li // CHECK: %s1 = alloca %struct.s38, align 4
301*67e74705SXin Li // CHECK: %s2 = alloca %struct.s38, align 4
302*67e74705SXin Li // CHECK: store i64 %s1.coerce, i64* %{{.*}}, align 4
303*67e74705SXin Li // CHECK: store i64 %s2.coerce, i64* %{{.*}}, align 4
304*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s1, i32 0, i32 0
305*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s2, i32 0, i32 0
306*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s1, i32 0, i32 1
307*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s38, %struct.s38* %s2, i32 0, i32 1
308*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
309*67e74705SXin Li }
caller38_stack()310*67e74705SXin Li int caller38_stack() {
311*67e74705SXin Li // CHECK: define i32 @caller38_stack()
312*67e74705SXin Li // CHECK: %[[a:.*]] = load i64, i64* bitcast (%struct.s38* @g38 to i64*), align 4
313*67e74705SXin Li // CHECK: %[[b:.*]] = load i64, i64* bitcast (%struct.s38* @g38_2 to i64*), align 4
314*67e74705SXin Li // CHECK: call i32 @f38_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i64 %[[a]], i64 %[[b]])
315*67e74705SXin Li return f38_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g38, g38_2);
316*67e74705SXin Li }
317*67e74705SXin Li
318*67e74705SXin Li // structs with size <= 8 bytes, with alignment attribute
319*67e74705SXin Li struct s39
320*67e74705SXin Li {
321*67e74705SXin Li int i;
322*67e74705SXin Li short s;
323*67e74705SXin Li } __attribute__((aligned(16)));
324*67e74705SXin Li typedef struct s39 s39_with_align;
325*67e74705SXin Li // passing aligned structs in registers
326*67e74705SXin Li __attribute__ ((noinline))
f39(int i,s39_with_align s1,s39_with_align s2)327*67e74705SXin Li int f39(int i, s39_with_align s1, s39_with_align s2) {
328*67e74705SXin Li // CHECK: define i32 @f39(i32 %i, i128 %s1.coerce, i128 %s2.coerce)
329*67e74705SXin Li // CHECK: %s1 = alloca %struct.s39, align 16
330*67e74705SXin Li // CHECK: %s2 = alloca %struct.s39, align 16
331*67e74705SXin Li // CHECK: store i128 %s1.coerce, i128* %{{.*}}, align 16
332*67e74705SXin Li // CHECK: store i128 %s2.coerce, i128* %{{.*}}, align 16
333*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s1, i32 0, i32 0
334*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s2, i32 0, i32 0
335*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s1, i32 0, i32 1
336*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s2, i32 0, i32 1
337*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
338*67e74705SXin Li }
339*67e74705SXin Li s39_with_align g39;
340*67e74705SXin Li s39_with_align g39_2;
caller39()341*67e74705SXin Li int caller39() {
342*67e74705SXin Li // CHECK: define i32 @caller39()
343*67e74705SXin Li // CHECK: %[[a:.*]] = load i128, i128* bitcast (%struct.s39* @g39 to i128*), align 16
344*67e74705SXin Li // CHECK: %[[b:.*]] = load i128, i128* bitcast (%struct.s39* @g39_2 to i128*), align 16
345*67e74705SXin Li // CHECK: call i32 @f39(i32 3, i128 %[[a]], i128 %[[b]])
346*67e74705SXin Li return f39(3, g39, g39_2);
347*67e74705SXin Li }
348*67e74705SXin Li // passing aligned structs on stack
349*67e74705SXin Li __attribute__ ((noinline))
f39_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s39_with_align s1,s39_with_align s2)350*67e74705SXin Li int f39_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
351*67e74705SXin Li int i9, s39_with_align s1, s39_with_align s2) {
352*67e74705SXin Li // CHECK: define i32 @f39_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i128 %s1.coerce, i128 %s2.coerce)
353*67e74705SXin Li // CHECK: %s1 = alloca %struct.s39, align 16
354*67e74705SXin Li // CHECK: %s2 = alloca %struct.s39, align 16
355*67e74705SXin Li // CHECK: store i128 %s1.coerce, i128* %{{.*}}, align 16
356*67e74705SXin Li // CHECK: store i128 %s2.coerce, i128* %{{.*}}, align 16
357*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s1, i32 0, i32 0
358*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s2, i32 0, i32 0
359*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s1, i32 0, i32 1
360*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s39, %struct.s39* %s2, i32 0, i32 1
361*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
362*67e74705SXin Li }
caller39_stack()363*67e74705SXin Li int caller39_stack() {
364*67e74705SXin Li // CHECK: define i32 @caller39_stack()
365*67e74705SXin Li // CHECK: %[[a:.*]] = load i128, i128* bitcast (%struct.s39* @g39 to i128*), align 16
366*67e74705SXin Li // CHECK: %[[b:.*]] = load i128, i128* bitcast (%struct.s39* @g39_2 to i128*), align 16
367*67e74705SXin Li // CHECK: call i32 @f39_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i128 %[[a]], i128 %[[b]])
368*67e74705SXin Li return f39_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g39, g39_2);
369*67e74705SXin Li }
370*67e74705SXin Li
371*67e74705SXin Li // structs with size <= 16 bytes, without alignment attribute
372*67e74705SXin Li struct s40
373*67e74705SXin Li {
374*67e74705SXin Li int i;
375*67e74705SXin Li short s;
376*67e74705SXin Li int i2;
377*67e74705SXin Li short s2;
378*67e74705SXin Li };
379*67e74705SXin Li typedef struct s40 s40_no_align;
380*67e74705SXin Li // passing structs in registers
381*67e74705SXin Li __attribute__ ((noinline))
f40(int i,s40_no_align s1,s40_no_align s2)382*67e74705SXin Li int f40(int i, s40_no_align s1, s40_no_align s2) {
383*67e74705SXin Li // CHECK: define i32 @f40(i32 %i, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce)
384*67e74705SXin Li // CHECK: %s1 = alloca %struct.s40, align 4
385*67e74705SXin Li // CHECK: %s2 = alloca %struct.s40, align 4
386*67e74705SXin Li // CHECK: store [2 x i64] %s1.coerce, [2 x i64]* %{{.*}}, align 4
387*67e74705SXin Li // CHECK: store [2 x i64] %s2.coerce, [2 x i64]* %{{.*}}, align 4
388*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s1, i32 0, i32 0
389*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s2, i32 0, i32 0
390*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s1, i32 0, i32 1
391*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s2, i32 0, i32 1
392*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
393*67e74705SXin Li }
394*67e74705SXin Li s40_no_align g40;
395*67e74705SXin Li s40_no_align g40_2;
caller40()396*67e74705SXin Li int caller40() {
397*67e74705SXin Li // CHECK: define i32 @caller40()
398*67e74705SXin Li // CHECK: %[[a:.*]] = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40 to [2 x i64]*), align 4
399*67e74705SXin Li // CHECK: %[[b:.*]] = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40_2 to [2 x i64]*), align 4
400*67e74705SXin Li // CHECK: call i32 @f40(i32 3, [2 x i64] %[[a]], [2 x i64] %[[b]])
401*67e74705SXin Li return f40(3, g40, g40_2);
402*67e74705SXin Li }
403*67e74705SXin Li // passing structs on stack
404*67e74705SXin Li __attribute__ ((noinline))
f40_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s40_no_align s1,s40_no_align s2)405*67e74705SXin Li int f40_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
406*67e74705SXin Li int i9, s40_no_align s1, s40_no_align s2) {
407*67e74705SXin Li // CHECK: define i32 @f40_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce)
408*67e74705SXin Li // CHECK: %s1 = alloca %struct.s40, align 4
409*67e74705SXin Li // CHECK: %s2 = alloca %struct.s40, align 4
410*67e74705SXin Li // CHECK: store [2 x i64] %s1.coerce, [2 x i64]* %{{.*}}, align 4
411*67e74705SXin Li // CHECK: store [2 x i64] %s2.coerce, [2 x i64]* %{{.*}}, align 4
412*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s1, i32 0, i32 0
413*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s2, i32 0, i32 0
414*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s1, i32 0, i32 1
415*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s40, %struct.s40* %s2, i32 0, i32 1
416*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
417*67e74705SXin Li }
caller40_stack()418*67e74705SXin Li int caller40_stack() {
419*67e74705SXin Li // CHECK: define i32 @caller40_stack()
420*67e74705SXin Li // CHECK: %[[a:.*]] = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40 to [2 x i64]*), align 4
421*67e74705SXin Li // CHECK: %[[b:.*]] = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40_2 to [2 x i64]*), align 4
422*67e74705SXin Li // CHECK: call i32 @f40_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, [2 x i64] %[[a]], [2 x i64] %[[b]])
423*67e74705SXin Li return f40_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g40, g40_2);
424*67e74705SXin Li }
425*67e74705SXin Li
426*67e74705SXin Li // structs with size <= 16 bytes, with alignment attribute
427*67e74705SXin Li struct s41
428*67e74705SXin Li {
429*67e74705SXin Li int i;
430*67e74705SXin Li short s;
431*67e74705SXin Li int i2;
432*67e74705SXin Li short s2;
433*67e74705SXin Li } __attribute__((aligned(16)));
434*67e74705SXin Li typedef struct s41 s41_with_align;
435*67e74705SXin Li // passing aligned structs in registers
436*67e74705SXin Li __attribute__ ((noinline))
f41(int i,s41_with_align s1,s41_with_align s2)437*67e74705SXin Li int f41(int i, s41_with_align s1, s41_with_align s2) {
438*67e74705SXin Li // CHECK: define i32 @f41(i32 %i, i128 %s1.coerce, i128 %s2.coerce)
439*67e74705SXin Li // CHECK: %s1 = alloca %struct.s41, align 16
440*67e74705SXin Li // CHECK: %s2 = alloca %struct.s41, align 16
441*67e74705SXin Li // CHECK: store i128 %s1.coerce, i128* %{{.*}}, align 16
442*67e74705SXin Li // CHECK: store i128 %s2.coerce, i128* %{{.*}}, align 16
443*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s1, i32 0, i32 0
444*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s2, i32 0, i32 0
445*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s1, i32 0, i32 1
446*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s2, i32 0, i32 1
447*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
448*67e74705SXin Li }
449*67e74705SXin Li s41_with_align g41;
450*67e74705SXin Li s41_with_align g41_2;
caller41()451*67e74705SXin Li int caller41() {
452*67e74705SXin Li // CHECK: define i32 @caller41()
453*67e74705SXin Li // CHECK: %[[a:.*]] = load i128, i128* bitcast (%struct.s41* @g41 to i128*), align 16
454*67e74705SXin Li // CHECK: %[[b:.*]] = load i128, i128* bitcast (%struct.s41* @g41_2 to i128*), align 16
455*67e74705SXin Li // CHECK: call i32 @f41(i32 3, i128 %[[a]], i128 %[[b]])
456*67e74705SXin Li return f41(3, g41, g41_2);
457*67e74705SXin Li }
458*67e74705SXin Li // passing aligned structs on stack
459*67e74705SXin Li __attribute__ ((noinline))
f41_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s41_with_align s1,s41_with_align s2)460*67e74705SXin Li int f41_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
461*67e74705SXin Li int i9, s41_with_align s1, s41_with_align s2) {
462*67e74705SXin Li // CHECK: define i32 @f41_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i128 %s1.coerce, i128 %s2.coerce)
463*67e74705SXin Li // CHECK: %s1 = alloca %struct.s41, align 16
464*67e74705SXin Li // CHECK: %s2 = alloca %struct.s41, align 16
465*67e74705SXin Li // CHECK: store i128 %s1.coerce, i128* %{{.*}}, align 16
466*67e74705SXin Li // CHECK: store i128 %s2.coerce, i128* %{{.*}}, align 16
467*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s1, i32 0, i32 0
468*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s2, i32 0, i32 0
469*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s1, i32 0, i32 1
470*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s41, %struct.s41* %s2, i32 0, i32 1
471*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
472*67e74705SXin Li }
caller41_stack()473*67e74705SXin Li int caller41_stack() {
474*67e74705SXin Li // CHECK: define i32 @caller41_stack()
475*67e74705SXin Li // CHECK: %[[a:.*]] = load i128, i128* bitcast (%struct.s41* @g41 to i128*), align 16
476*67e74705SXin Li // CHECK: %[[b:.*]] = load i128, i128* bitcast (%struct.s41* @g41_2 to i128*), align 16
477*67e74705SXin Li // CHECK: call i32 @f41_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i128 %[[a]], i128 %[[b]])
478*67e74705SXin Li return f41_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g41, g41_2);
479*67e74705SXin Li }
480*67e74705SXin Li
481*67e74705SXin Li // structs with size > 16 bytes, without alignment attribute
482*67e74705SXin Li struct s42
483*67e74705SXin Li {
484*67e74705SXin Li int i;
485*67e74705SXin Li short s;
486*67e74705SXin Li int i2;
487*67e74705SXin Li short s2;
488*67e74705SXin Li int i3;
489*67e74705SXin Li short s3;
490*67e74705SXin Li };
491*67e74705SXin Li typedef struct s42 s42_no_align;
492*67e74705SXin Li // passing structs in registers
493*67e74705SXin Li __attribute__ ((noinline))
f42(int i,s42_no_align s1,s42_no_align s2)494*67e74705SXin Li int f42(int i, s42_no_align s1, s42_no_align s2) {
495*67e74705SXin Li // CHECK: define i32 @f42(i32 %i, %struct.s42* %s1, %struct.s42* %s2)
496*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s1, i32 0, i32 0
497*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s2, i32 0, i32 0
498*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s1, i32 0, i32 1
499*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s2, i32 0, i32 1
500*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
501*67e74705SXin Li }
502*67e74705SXin Li s42_no_align g42;
503*67e74705SXin Li s42_no_align g42_2;
caller42()504*67e74705SXin Li int caller42() {
505*67e74705SXin Li // CHECK: define i32 @caller42()
506*67e74705SXin Li // CHECK: %[[a:.*]] = alloca %struct.s42, align 4
507*67e74705SXin Li // CHECK: %[[b:.*]] = alloca %struct.s42, align 4
508*67e74705SXin Li // CHECK: %[[c:.*]] = bitcast %struct.s42* %[[a]] to i8*
509*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
510*67e74705SXin Li // CHECK: %[[d:.*]] = bitcast %struct.s42* %[[b]] to i8*
511*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
512*67e74705SXin Li // CHECK: call i32 @f42(i32 3, %struct.s42* %[[a]], %struct.s42* %[[b]])
513*67e74705SXin Li return f42(3, g42, g42_2);
514*67e74705SXin Li }
515*67e74705SXin Li // passing structs on stack
516*67e74705SXin Li __attribute__ ((noinline))
f42_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s42_no_align s1,s42_no_align s2)517*67e74705SXin Li int f42_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
518*67e74705SXin Li int i9, s42_no_align s1, s42_no_align s2) {
519*67e74705SXin Li // CHECK: define i32 @f42_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, %struct.s42* %s1, %struct.s42* %s2)
520*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s1, i32 0, i32 0
521*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s2, i32 0, i32 0
522*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s1, i32 0, i32 1
523*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s42, %struct.s42* %s2, i32 0, i32 1
524*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
525*67e74705SXin Li }
caller42_stack()526*67e74705SXin Li int caller42_stack() {
527*67e74705SXin Li // CHECK: define i32 @caller42_stack()
528*67e74705SXin Li // CHECK: %[[a:.*]] = alloca %struct.s42, align 4
529*67e74705SXin Li // CHECK: %[[b:.*]] = alloca %struct.s42, align 4
530*67e74705SXin Li // CHECK: %[[c:.*]] = bitcast %struct.s42* %[[a]] to i8*
531*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
532*67e74705SXin Li // CHECK: %[[d:.*]] = bitcast %struct.s42* %[[b]] to i8*
533*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
534*67e74705SXin Li // CHECK: call i32 @f42_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, %struct.s42* %[[a]], %struct.s42* %[[b]])
535*67e74705SXin Li return f42_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g42, g42_2);
536*67e74705SXin Li }
537*67e74705SXin Li
538*67e74705SXin Li // structs with size > 16 bytes, with alignment attribute
539*67e74705SXin Li struct s43
540*67e74705SXin Li {
541*67e74705SXin Li int i;
542*67e74705SXin Li short s;
543*67e74705SXin Li int i2;
544*67e74705SXin Li short s2;
545*67e74705SXin Li int i3;
546*67e74705SXin Li short s3;
547*67e74705SXin Li } __attribute__((aligned(16)));
548*67e74705SXin Li typedef struct s43 s43_with_align;
549*67e74705SXin Li // passing aligned structs in registers
550*67e74705SXin Li __attribute__ ((noinline))
f43(int i,s43_with_align s1,s43_with_align s2)551*67e74705SXin Li int f43(int i, s43_with_align s1, s43_with_align s2) {
552*67e74705SXin Li // CHECK: define i32 @f43(i32 %i, %struct.s43* %s1, %struct.s43* %s2)
553*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s1, i32 0, i32 0
554*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s2, i32 0, i32 0
555*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s1, i32 0, i32 1
556*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s2, i32 0, i32 1
557*67e74705SXin Li return s1.i + s2.i + i + s1.s + s2.s;
558*67e74705SXin Li }
559*67e74705SXin Li s43_with_align g43;
560*67e74705SXin Li s43_with_align g43_2;
caller43()561*67e74705SXin Li int caller43() {
562*67e74705SXin Li // CHECK: define i32 @caller43()
563*67e74705SXin Li // CHECK: %[[a:.*]] = alloca %struct.s43, align 16
564*67e74705SXin Li // CHECK: %[[b:.*]] = alloca %struct.s43, align 16
565*67e74705SXin Li // CHECK: %[[c:.*]] = bitcast %struct.s43* %[[a]] to i8*
566*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
567*67e74705SXin Li // CHECK: %[[d:.*]] = bitcast %struct.s43* %[[b]] to i8*
568*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
569*67e74705SXin Li // CHECK: call i32 @f43(i32 3, %struct.s43* %[[a]], %struct.s43* %[[b]])
570*67e74705SXin Li return f43(3, g43, g43_2);
571*67e74705SXin Li }
572*67e74705SXin Li // passing aligned structs on stack
573*67e74705SXin Li __attribute__ ((noinline))
f43_stack(int i,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9,s43_with_align s1,s43_with_align s2)574*67e74705SXin Li int f43_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
575*67e74705SXin Li int i9, s43_with_align s1, s43_with_align s2) {
576*67e74705SXin Li // CHECK: define i32 @f43_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, %struct.s43* %s1, %struct.s43* %s2)
577*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s1, i32 0, i32 0
578*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s2, i32 0, i32 0
579*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s1, i32 0, i32 1
580*67e74705SXin Li // CHECK: getelementptr inbounds %struct.s43, %struct.s43* %s2, i32 0, i32 1
581*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + s1.s + s2.s;
582*67e74705SXin Li }
caller43_stack()583*67e74705SXin Li int caller43_stack() {
584*67e74705SXin Li // CHECK: define i32 @caller43_stack()
585*67e74705SXin Li // CHECK: %[[a:.*]] = alloca %struct.s43, align 16
586*67e74705SXin Li // CHECK: %[[b:.*]] = alloca %struct.s43, align 16
587*67e74705SXin Li // CHECK: %[[c:.*]] = bitcast %struct.s43* %[[a]] to i8*
588*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
589*67e74705SXin Li // CHECK: %[[d:.*]] = bitcast %struct.s43* %[[b]] to i8*
590*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
591*67e74705SXin Li // CHECK: call i32 @f43_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, %struct.s43* %[[a]], %struct.s43* %[[b]])
592*67e74705SXin Li return f43_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g43, g43_2);
593*67e74705SXin Li }
594*67e74705SXin Li
595*67e74705SXin Li // rdar://13668927
596*67e74705SXin Li // We should not split argument s1 between registers and stack.
597*67e74705SXin Li __attribute__ ((noinline))
f40_split(int i,int i2,int i3,int i4,int i5,int i6,int i7,s40_no_align s1,s40_no_align s2)598*67e74705SXin Li int f40_split(int i, int i2, int i3, int i4, int i5, int i6, int i7,
599*67e74705SXin Li s40_no_align s1, s40_no_align s2) {
600*67e74705SXin Li // CHECK: define i32 @f40_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce)
601*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + s1.s + s2.s;
602*67e74705SXin Li }
caller40_split()603*67e74705SXin Li int caller40_split() {
604*67e74705SXin Li // CHECK: define i32 @caller40_split()
605*67e74705SXin Li // CHECK: call i32 @f40_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, [2 x i64] %{{.*}} [2 x i64] %{{.*}})
606*67e74705SXin Li return f40_split(1, 2, 3, 4, 5, 6, 7, g40, g40_2);
607*67e74705SXin Li }
608*67e74705SXin Li
609*67e74705SXin Li __attribute__ ((noinline))
f41_split(int i,int i2,int i3,int i4,int i5,int i6,int i7,s41_with_align s1,s41_with_align s2)610*67e74705SXin Li int f41_split(int i, int i2, int i3, int i4, int i5, int i6, int i7,
611*67e74705SXin Li s41_with_align s1, s41_with_align s2) {
612*67e74705SXin Li // CHECK: define i32 @f41_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i128 %s1.coerce, i128 %s2.coerce)
613*67e74705SXin Li return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + s1.s + s2.s;
614*67e74705SXin Li }
caller41_split()615*67e74705SXin Li int caller41_split() {
616*67e74705SXin Li // CHECK: define i32 @caller41_split()
617*67e74705SXin Li // CHECK: call i32 @f41_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i128 %{{.*}}, i128 %{{.*}})
618*67e74705SXin Li return f41_split(1, 2, 3, 4, 5, 6, 7, g41, g41_2);
619*67e74705SXin Li }
620*67e74705SXin Li
621*67e74705SXin Li // Handle homogeneous aggregates properly in variadic functions.
622*67e74705SXin Li struct HFA {
623*67e74705SXin Li float a, b, c, d;
624*67e74705SXin Li };
625*67e74705SXin Li
test_hfa(int n,...)626*67e74705SXin Li float test_hfa(int n, ...) {
627*67e74705SXin Li // CHECK-LABEL: define float @test_hfa(i32 %n, ...)
628*67e74705SXin Li // CHECK: [[THELIST:%.*]] = alloca i8*
629*67e74705SXin Li // CHECK: [[CURLIST:%.*]] = load i8*, i8** [[THELIST]]
630*67e74705SXin Li
631*67e74705SXin Li // HFA is not indirect, so occupies its full 16 bytes on the stack.
632*67e74705SXin Li // CHECK: [[NEXTLIST:%.*]] = getelementptr inbounds i8, i8* [[CURLIST]], i64 16
633*67e74705SXin Li // CHECK: store i8* [[NEXTLIST]], i8** [[THELIST]]
634*67e74705SXin Li
635*67e74705SXin Li // CHECK: bitcast i8* [[CURLIST]] to %struct.HFA*
636*67e74705SXin Li __builtin_va_list thelist;
637*67e74705SXin Li __builtin_va_start(thelist, n);
638*67e74705SXin Li struct HFA h = __builtin_va_arg(thelist, struct HFA);
639*67e74705SXin Li return h.d;
640*67e74705SXin Li }
641*67e74705SXin Li
test_hfa_call(struct HFA * a)642*67e74705SXin Li float test_hfa_call(struct HFA *a) {
643*67e74705SXin Li // CHECK-LABEL: define float @test_hfa_call(%struct.HFA* %a)
644*67e74705SXin Li // CHECK: call float (i32, ...) @test_hfa(i32 1, [4 x float] {{.*}})
645*67e74705SXin Li test_hfa(1, *a);
646*67e74705SXin Li }
647*67e74705SXin Li
648*67e74705SXin Li struct TooBigHFA {
649*67e74705SXin Li float a, b, c, d, e;
650*67e74705SXin Li };
651*67e74705SXin Li
test_toobig_hfa(int n,...)652*67e74705SXin Li float test_toobig_hfa(int n, ...) {
653*67e74705SXin Li // CHECK-LABEL: define float @test_toobig_hfa(i32 %n, ...)
654*67e74705SXin Li // CHECK: [[THELIST:%.*]] = alloca i8*
655*67e74705SXin Li // CHECK: [[CURLIST:%.*]] = load i8*, i8** [[THELIST]]
656*67e74705SXin Li
657*67e74705SXin Li // TooBigHFA is not actually an HFA, so gets passed indirectly. Only 8 bytes
658*67e74705SXin Li // of stack consumed.
659*67e74705SXin Li // CHECK: [[NEXTLIST:%.*]] = getelementptr inbounds i8, i8* [[CURLIST]], i64 8
660*67e74705SXin Li // CHECK: store i8* [[NEXTLIST]], i8** [[THELIST]]
661*67e74705SXin Li
662*67e74705SXin Li // CHECK: [[HFAPTRPTR:%.*]] = bitcast i8* [[CURLIST]] to %struct.TooBigHFA**
663*67e74705SXin Li // CHECK: [[HFAPTR:%.*]] = load %struct.TooBigHFA*, %struct.TooBigHFA** [[HFAPTRPTR]]
664*67e74705SXin Li __builtin_va_list thelist;
665*67e74705SXin Li __builtin_va_start(thelist, n);
666*67e74705SXin Li struct TooBigHFA h = __builtin_va_arg(thelist, struct TooBigHFA);
667*67e74705SXin Li return h.d;
668*67e74705SXin Li }
669*67e74705SXin Li
670*67e74705SXin Li struct HVA {
671*67e74705SXin Li int32x4_t a, b;
672*67e74705SXin Li };
673*67e74705SXin Li
test_hva(int n,...)674*67e74705SXin Li int32x4_t test_hva(int n, ...) {
675*67e74705SXin Li // CHECK-LABEL: define <4 x i32> @test_hva(i32 %n, ...)
676*67e74705SXin Li // CHECK: [[THELIST:%.*]] = alloca i8*
677*67e74705SXin Li // CHECK: [[CURLIST:%.*]] = load i8*, i8** [[THELIST]]
678*67e74705SXin Li
679*67e74705SXin Li // HVA is not indirect, so occupies its full 16 bytes on the stack. but it
680*67e74705SXin Li // must be properly aligned.
681*67e74705SXin Li // CHECK: [[ALIGN0:%.*]] = ptrtoint i8* [[CURLIST]] to i64
682*67e74705SXin Li // CHECK: [[ALIGN1:%.*]] = add i64 [[ALIGN0]], 15
683*67e74705SXin Li // CHECK: [[ALIGN2:%.*]] = and i64 [[ALIGN1]], -16
684*67e74705SXin Li // CHECK: [[ALIGNED_LIST:%.*]] = inttoptr i64 [[ALIGN2]] to i8*
685*67e74705SXin Li
686*67e74705SXin Li // CHECK: [[NEXTLIST:%.*]] = getelementptr inbounds i8, i8* [[ALIGNED_LIST]], i64 32
687*67e74705SXin Li // CHECK: store i8* [[NEXTLIST]], i8** [[THELIST]]
688*67e74705SXin Li
689*67e74705SXin Li // CHECK: bitcast i8* [[ALIGNED_LIST]] to %struct.HVA*
690*67e74705SXin Li __builtin_va_list thelist;
691*67e74705SXin Li __builtin_va_start(thelist, n);
692*67e74705SXin Li struct HVA h = __builtin_va_arg(thelist, struct HVA);
693*67e74705SXin Li return h.b;
694*67e74705SXin Li }
695*67e74705SXin Li
696*67e74705SXin Li struct TooBigHVA {
697*67e74705SXin Li int32x4_t a, b, c, d, e;
698*67e74705SXin Li };
699*67e74705SXin Li
test_toobig_hva(int n,...)700*67e74705SXin Li int32x4_t test_toobig_hva(int n, ...) {
701*67e74705SXin Li // CHECK-LABEL: define <4 x i32> @test_toobig_hva(i32 %n, ...)
702*67e74705SXin Li // CHECK: [[THELIST:%.*]] = alloca i8*
703*67e74705SXin Li // CHECK: [[CURLIST:%.*]] = load i8*, i8** [[THELIST]]
704*67e74705SXin Li
705*67e74705SXin Li // TooBigHVA is not actually an HVA, so gets passed indirectly. Only 8 bytes
706*67e74705SXin Li // of stack consumed.
707*67e74705SXin Li // CHECK: [[NEXTLIST:%.*]] = getelementptr inbounds i8, i8* [[CURLIST]], i64 8
708*67e74705SXin Li // CHECK: store i8* [[NEXTLIST]], i8** [[THELIST]]
709*67e74705SXin Li
710*67e74705SXin Li // CHECK: [[HVAPTRPTR:%.*]] = bitcast i8* [[CURLIST]] to %struct.TooBigHVA**
711*67e74705SXin Li // CHECK: [[HVAPTR:%.*]] = load %struct.TooBigHVA*, %struct.TooBigHVA** [[HVAPTRPTR]]
712*67e74705SXin Li __builtin_va_list thelist;
713*67e74705SXin Li __builtin_va_start(thelist, n);
714*67e74705SXin Li struct TooBigHVA h = __builtin_va_arg(thelist, struct TooBigHVA);
715*67e74705SXin Li return h.d;
716*67e74705SXin Li }
717*67e74705SXin Li
718*67e74705SXin Li typedef __attribute__((__ext_vector_type__(3))) float float32x3_t;
719*67e74705SXin Li typedef struct { float32x3_t arr[4]; } HFAv3;
720*67e74705SXin Li
test_hva_v3(int n,...)721*67e74705SXin Li float32x3_t test_hva_v3(int n, ...) {
722*67e74705SXin Li // CHECK-LABEL: define <3 x float> @test_hva_v3(i32 %n, ...)
723*67e74705SXin Li // CHECK: [[THELIST:%.*]] = alloca i8*
724*67e74705SXin Li // CHECK: [[CURLIST:%.*]] = load i8*, i8** [[THELIST]]
725*67e74705SXin Li
726*67e74705SXin Li // HVA is not indirect, so occupies its full 16 bytes on the stack. but it
727*67e74705SXin Li // must be properly aligned.
728*67e74705SXin Li // CHECK: [[ALIGN0:%.*]] = ptrtoint i8* [[CURLIST]] to i64
729*67e74705SXin Li // CHECK: [[ALIGN1:%.*]] = add i64 [[ALIGN0]], 15
730*67e74705SXin Li // CHECK: [[ALIGN2:%.*]] = and i64 [[ALIGN1]], -16
731*67e74705SXin Li // CHECK: [[ALIGNED_LIST:%.*]] = inttoptr i64 [[ALIGN2]] to i8*
732*67e74705SXin Li
733*67e74705SXin Li // CHECK: [[NEXTLIST:%.*]] = getelementptr inbounds i8, i8* [[ALIGNED_LIST]], i64 64
734*67e74705SXin Li // CHECK: store i8* [[NEXTLIST]], i8** [[THELIST]]
735*67e74705SXin Li
736*67e74705SXin Li // CHECK: bitcast i8* [[ALIGNED_LIST]] to %struct.HFAv3*
737*67e74705SXin Li __builtin_va_list l;
738*67e74705SXin Li __builtin_va_start(l, n);
739*67e74705SXin Li HFAv3 r = __builtin_va_arg(l, HFAv3);
740*67e74705SXin Li return r.arr[2];
741*67e74705SXin Li }
742*67e74705SXin Li
test_hva_v3_call(HFAv3 * a)743*67e74705SXin Li float32x3_t test_hva_v3_call(HFAv3 *a) {
744*67e74705SXin Li // CHECK-LABEL: define <3 x float> @test_hva_v3_call(%struct.HFAv3* %a)
745*67e74705SXin Li // CHECK: call <3 x float> (i32, ...) @test_hva_v3(i32 1, [4 x <4 x float>] {{.*}})
746*67e74705SXin Li return test_hva_v3(1, *a);
747*67e74705SXin Li }
748