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