1// RUN: %clang_cc1 -triple arm64-apple-ios7 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple aarch64-linux-android -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s
3
4#include <stdarg.h>
5
6typedef __attribute__(( ext_vector_type(2) ))  char __char2;
7typedef __attribute__(( ext_vector_type(3) ))  char __char3;
8typedef __attribute__(( ext_vector_type(4) ))  char __char4;
9typedef __attribute__(( ext_vector_type(5) ))  char __char5;
10typedef __attribute__(( ext_vector_type(9) ))  char __char9;
11typedef __attribute__(( ext_vector_type(19) )) char __char19;
12typedef __attribute__(( ext_vector_type(3) ))  short __short3;
13typedef __attribute__(( ext_vector_type(5) ))  short __short5;
14typedef __attribute__(( ext_vector_type(3) ))  int __int3;
15typedef __attribute__(( ext_vector_type(5) ))  int __int5;
16typedef __attribute__(( ext_vector_type(3) ))  double __double3;
17
18// Passing legal vector types as varargs. Check that we've allocated the appropriate size
19double varargs_vec_2c(int fixed, ...) {
20// ANDROID: varargs_vec_2c
21// ANDROID: [[VAR:%.*]] = alloca <2 x i8>, align 2
22// ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
23// ANDROID: bitcast i8* [[AP_CUR]] to <2 x i8>*
24  va_list ap;
25  double sum = fixed;
26  va_start(ap, fixed);
27  __char2 c3 = va_arg(ap, __char2);
28  sum = sum + c3.x + c3.y;
29  va_end(ap);
30  return sum;
31}
32
33double test_2c(__char2 *in) {
34// ANDROID: call double (i32, ...) @varargs_vec_2c(i32 3, i16 {{%.*}})
35  return varargs_vec_2c(3, *in);
36}
37
38double varargs_vec_3c(int fixed, ...) {
39// CHECK: varargs_vec_3c
40// CHECK: alloca <3 x i8>, align 4
41// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
42// CHECK: bitcast i8* [[AP_CUR]] to <3 x i8>*
43  va_list ap;
44  double sum = fixed;
45  va_start(ap, fixed);
46  __char3 c3 = va_arg(ap, __char3);
47  sum = sum + c3.x + c3.y;
48  va_end(ap);
49  return sum;
50}
51
52double test_3c(__char3 *in) {
53// CHECK: test_3c
54// CHECK: call double (i32, ...) @varargs_vec_3c(i32 3, i32 {{%.*}})
55  return varargs_vec_3c(3, *in);
56}
57
58double varargs_vec_4c(int fixed, ...) {
59// CHECK: varargs_vec_4c
60// CHECK: alloca <4 x i8>, align 4
61// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
62// CHECK: bitcast i8* [[AP_CUR]] to <4 x i8>*
63  va_list ap;
64  double sum = fixed;
65  va_start(ap, fixed);
66  __char4 c4 = va_arg(ap, __char4);
67  sum = sum + c4.x + c4.y;
68  va_end(ap);
69  return sum;
70}
71
72double test_4c(__char4 *in) {
73// CHECK: test_4c
74// CHECK: call double (i32, ...) @varargs_vec_4c(i32 4, i32 {{%.*}})
75  return varargs_vec_4c(4, *in);
76}
77
78double varargs_vec_5c(int fixed, ...) {
79// CHECK: varargs_vec_5c
80// CHECK: alloca <5 x i8>, align 8
81// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
82// CHECK: bitcast i8* [[AP_CUR]] to <5 x i8>*
83  va_list ap;
84  double sum = fixed;
85  va_start(ap, fixed);
86  __char5 c5 = va_arg(ap, __char5);
87  sum = sum + c5.x + c5.y;
88  va_end(ap);
89  return sum;
90}
91
92double test_5c(__char5 *in) {
93// CHECK: test_5c
94// CHECK: call double (i32, ...) @varargs_vec_5c(i32 5, <2 x i32> {{%.*}})
95  return varargs_vec_5c(5, *in);
96}
97
98double varargs_vec_9c(int fixed, ...) {
99// CHECK: varargs_vec_9c
100// CHECK: alloca <9 x i8>, align 16
101// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
102// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
103// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
104// CHECK: bitcast i8* [[AP_ALIGN]] to <9 x i8>*
105  va_list ap;
106  double sum = fixed;
107  va_start(ap, fixed);
108  __char9 c9 = va_arg(ap, __char9);
109  sum = sum + c9.x + c9.y;
110  va_end(ap);
111  return sum;
112}
113
114double test_9c(__char9 *in) {
115// CHECK: test_9c
116// CHECK: call double (i32, ...) @varargs_vec_9c(i32 9, <4 x i32> {{%.*}})
117  return varargs_vec_9c(9, *in);
118}
119
120double varargs_vec_19c(int fixed, ...) {
121// CHECK: varargs_vec_19c
122// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
123// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <19 x i8>**
124// CHECK: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]]
125  va_list ap;
126  double sum = fixed;
127  va_start(ap, fixed);
128  __char19 c19 = va_arg(ap, __char19);
129  sum = sum + c19.x + c19.y;
130  va_end(ap);
131  return sum;
132}
133
134double test_19c(__char19 *in) {
135// CHECK: test_19c
136// CHECK: call double (i32, ...) @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}})
137  return varargs_vec_19c(19, *in);
138}
139
140double varargs_vec_3s(int fixed, ...) {
141// CHECK: varargs_vec_3s
142// CHECK: alloca <3 x i16>, align 8
143// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
144// CHECK: bitcast i8* [[AP_CUR]] to <3 x i16>*
145  va_list ap;
146  double sum = fixed;
147  va_start(ap, fixed);
148  __short3 c3 = va_arg(ap, __short3);
149  sum = sum + c3.x + c3.y;
150  va_end(ap);
151  return sum;
152}
153
154double test_3s(__short3 *in) {
155// CHECK: test_3s
156// CHECK: call double (i32, ...) @varargs_vec_3s(i32 3, <2 x i32> {{%.*}})
157  return varargs_vec_3s(3, *in);
158}
159
160double varargs_vec_5s(int fixed, ...) {
161// CHECK: varargs_vec_5s
162// CHECK: alloca <5 x i16>, align 16
163// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
164// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
165// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
166// CHECK: bitcast i8* [[AP_ALIGN]] to <5 x i16>*
167  va_list ap;
168  double sum = fixed;
169  va_start(ap, fixed);
170  __short5 c5 = va_arg(ap, __short5);
171  sum = sum + c5.x + c5.y;
172  va_end(ap);
173  return sum;
174}
175
176double test_5s(__short5 *in) {
177// CHECK: test_5s
178// CHECK: call double (i32, ...) @varargs_vec_5s(i32 5, <4 x i32> {{%.*}})
179  return varargs_vec_5s(5, *in);
180}
181
182double varargs_vec_3i(int fixed, ...) {
183// CHECK: varargs_vec_3i
184// CHECK: alloca <3 x i32>, align 16
185// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
186// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
187// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
188// CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i32>*
189  va_list ap;
190  double sum = fixed;
191  va_start(ap, fixed);
192  __int3 c3 = va_arg(ap, __int3);
193  sum = sum + c3.x + c3.y;
194  va_end(ap);
195  return sum;
196}
197
198double test_3i(__int3 *in) {
199// CHECK: test_3i
200// CHECK: call double (i32, ...) @varargs_vec_3i(i32 3, <4 x i32> {{%.*}})
201  return varargs_vec_3i(3, *in);
202}
203
204double varargs_vec_5i(int fixed, ...) {
205// CHECK: varargs_vec_5i
206// CHECK: alloca <5 x i32>, align 16
207// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
208// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <5 x i32>**
209// CHECK: [[VAR2:%.*]] = load <5 x i32>*, <5 x i32>** [[VAR]]
210  va_list ap;
211  double sum = fixed;
212  va_start(ap, fixed);
213  __int5 c5 = va_arg(ap, __int5);
214  sum = sum + c5.x + c5.y;
215  va_end(ap);
216  return sum;
217}
218
219double test_5i(__int5 *in) {
220// CHECK: test_5i
221// CHECK: call double (i32, ...) @varargs_vec_5i(i32 5, <5 x i32>* {{%.*}})
222  return varargs_vec_5i(5, *in);
223}
224
225double varargs_vec_3d(int fixed, ...) {
226// CHECK: varargs_vec_3d
227// CHECK: alloca <3 x double>, align 16
228// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
229// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <3 x double>**
230// CHECK: [[VAR2:%.*]] = load <3 x double>*, <3 x double>** [[VAR]]
231  va_list ap;
232  double sum = fixed;
233  va_start(ap, fixed);
234  __double3 c3 = va_arg(ap, __double3);
235  sum = sum + c3.x + c3.y;
236  va_end(ap);
237  return sum;
238}
239
240double test_3d(__double3 *in) {
241// CHECK: test_3d
242// CHECK: call double (i32, ...) @varargs_vec_3d(i32 3, <3 x double>* {{%.*}})
243  return varargs_vec_3d(3, *in);
244}
245
246double varargs_vec(int fixed, ...) {
247// CHECK: varargs_vec
248  va_list ap;
249  double sum = fixed;
250  va_start(ap, fixed);
251  __char3 c3 = va_arg(ap, __char3);
252// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
253// CHECK: bitcast i8* [[AP_CUR]] to <3 x i8>*
254  sum = sum + c3.x + c3.y;
255  __char5 c5 = va_arg(ap, __char5);
256// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
257// CHECK: bitcast i8* [[AP_CUR]] to <5 x i8>*
258  sum = sum + c5.x + c5.y;
259  __char9 c9 = va_arg(ap, __char9);
260// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
261// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
262// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
263// CHECK: bitcast i8* [[AP_ALIGN]] to <9 x i8>*
264  sum = sum + c9.x + c9.y;
265  __char19 c19 = va_arg(ap, __char19);
266// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
267// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <19 x i8>**
268// CHECK: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]]
269  sum = sum + c19.x + c19.y;
270  __short3 s3 = va_arg(ap, __short3);
271// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
272// CHECK: bitcast i8* [[AP_CUR]] to <3 x i16>*
273  sum = sum + s3.x + s3.y;
274  __short5 s5 = va_arg(ap, __short5);
275// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
276// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
277// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
278// CHECK: bitcast i8* [[AP_ALIGN]] to <5 x i16>*
279  sum = sum + s5.x + s5.y;
280  __int3 i3 = va_arg(ap, __int3);
281// CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16
282// CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8*
283// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16
284// CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i32>*
285  sum = sum + i3.x + i3.y;
286  __int5 i5 = va_arg(ap, __int5);
287// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
288// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <5 x i32>**
289// CHECK: [[VAR2:%.*]] = load <5 x i32>*, <5 x i32>** [[VAR]]
290  sum = sum + i5.x + i5.y;
291  __double3 d3 = va_arg(ap, __double3);
292// CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8
293// CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <3 x double>**
294// CHECK: [[VAR2:%.*]] = load <3 x double>*, <3 x double>** [[VAR]]
295  sum = sum + d3.x + d3.y;
296  va_end(ap);
297  return sum;
298}
299
300double test(__char3 *c3, __char5 *c5, __char9 *c9, __char19 *c19,
301            __short3 *s3, __short5 *s5, __int3 *i3, __int5 *i5,
302            __double3 *d3) {
303  double ret = varargs_vec(3, *c3, *c5, *c9, *c19, *s3, *s5, *i3, *i5, *d3);
304// CHECK: call double (i32, ...) @varargs_vec(i32 3, i32 {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <19 x i8>* {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <5 x i32>* {{%.*}}, <3 x double>* {{%.*}})
305  return ret;
306}
307
308__attribute__((noinline)) double args_vec_3c(int fixed, __char3 c3) {
309// CHECK: args_vec_3c
310// CHECK: [[C3:%.*]] = alloca <3 x i8>, align 4
311// CHECK: [[TMP:%.*]] = bitcast <3 x i8>* [[C3]] to i32*
312// CHECK: store i32 {{%.*}}, i32* [[TMP]]
313  double sum = fixed;
314  sum = sum + c3.x + c3.y;
315  return sum;
316}
317
318double fixed_3c(__char3 *in) {
319// CHECK: fixed_3c
320// CHECK: call double @args_vec_3c(i32 3, i32 {{%.*}})
321  return args_vec_3c(3, *in);
322}
323
324__attribute__((noinline)) double args_vec_5c(int fixed, __char5 c5) {
325// CHECK: args_vec_5c
326// CHECK: [[C5:%.*]] = alloca <5 x i8>, align 8
327// CHECK: [[TMP:%.*]] = bitcast <5 x i8>* [[C5]] to <2 x i32>*
328// CHECK: store <2 x i32> {{%.*}}, <2 x i32>* [[TMP]], align 8
329  double sum = fixed;
330  sum = sum + c5.x + c5.y;
331  return sum;
332}
333
334double fixed_5c(__char5 *in) {
335// CHECK: fixed_5c
336// CHECK: call double @args_vec_5c(i32 5, <2 x i32> {{%.*}})
337  return args_vec_5c(5, *in);
338}
339
340__attribute__((noinline)) double args_vec_9c(int fixed, __char9 c9) {
341// CHECK: args_vec_9c
342// CHECK: [[C9:%.*]] = alloca <9 x i8>, align 16
343// CHECK: [[TMP:%.*]] = bitcast <9 x i8>* [[C9]] to <4 x i32>*
344// CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16
345  double sum = fixed;
346  sum = sum + c9.x + c9.y;
347  return sum;
348}
349
350double fixed_9c(__char9 *in) {
351// CHECK: fixed_9c
352// CHECK: call double @args_vec_9c(i32 9, <4 x i32> {{%.*}})
353  return args_vec_9c(9, *in);
354}
355
356__attribute__((noinline)) double args_vec_19c(int fixed, __char19 c19) {
357// CHECK: args_vec_19c
358// CHECK: [[C19:%.*]] = load <19 x i8>, <19 x i8>* {{.*}}, align 16
359  double sum = fixed;
360  sum = sum + c19.x + c19.y;
361  return sum;
362}
363
364double fixed_19c(__char19 *in) {
365// CHECK: fixed_19c
366// CHECK: call double @args_vec_19c(i32 19, <19 x i8>* {{%.*}})
367  return args_vec_19c(19, *in);
368}
369
370__attribute__((noinline)) double args_vec_3s(int fixed, __short3 c3) {
371// CHECK: args_vec_3s
372// CHECK: [[C3:%.*]] = alloca <3 x i16>, align 8
373// CHECK: [[TMP:%.*]] = bitcast <3 x i16>* [[C3]] to <2 x i32>*
374// CHECK: store <2 x i32> {{%.*}}, <2 x i32>* [[TMP]], align 8
375  double sum = fixed;
376  sum = sum + c3.x + c3.y;
377  return sum;
378}
379
380double fixed_3s(__short3 *in) {
381// CHECK: fixed_3s
382// CHECK: call double @args_vec_3s(i32 3, <2 x i32> {{%.*}})
383  return args_vec_3s(3, *in);
384}
385
386__attribute__((noinline)) double args_vec_5s(int fixed, __short5 c5) {
387// CHECK: args_vec_5s
388// CHECK: [[C5:%.*]] = alloca <5 x i16>, align 16
389// CHECK: [[TMP:%.*]] = bitcast <5 x i16>* [[C5]] to <4 x i32>*
390// CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16
391  double sum = fixed;
392  sum = sum + c5.x + c5.y;
393  return sum;
394}
395
396double fixed_5s(__short5 *in) {
397// CHECK: fixed_5s
398// CHECK: call double @args_vec_5s(i32 5, <4 x i32> {{%.*}})
399  return args_vec_5s(5, *in);
400}
401
402__attribute__((noinline)) double args_vec_3i(int fixed, __int3 c3) {
403// CHECK: args_vec_3i
404// CHECK: [[C3:%.*]] = alloca <3 x i32>, align 16
405// CHECK: [[TMP:%.*]] = bitcast <3 x i32>* [[C3]] to <4 x i32>*
406// CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16
407  double sum = fixed;
408  sum = sum + c3.x + c3.y;
409  return sum;
410}
411
412double fixed_3i(__int3 *in) {
413// CHECK: fixed_3i
414// CHECK: call double @args_vec_3i(i32 3, <4 x i32> {{%.*}})
415  return args_vec_3i(3, *in);
416}
417
418__attribute__((noinline)) double args_vec_5i(int fixed, __int5 c5) {
419// CHECK: args_vec_5i
420// CHECK: [[C5:%.*]] = load <5 x i32>, <5 x i32>* {{%.*}}, align 16
421  double sum = fixed;
422  sum = sum + c5.x + c5.y;
423  return sum;
424}
425
426double fixed_5i(__int5 *in) {
427// CHECK: fixed_5i
428// CHECK: call double @args_vec_5i(i32 5, <5 x i32>* {{%.*}})
429  return args_vec_5i(5, *in);
430}
431
432__attribute__((noinline)) double args_vec_3d(int fixed, __double3 c3) {
433// CHECK: args_vec_3d
434// CHECK: [[CAST:%.*]] = bitcast <3 x double>* {{%.*}} to <4 x double>*
435// CHECK: [[LOAD:%.*]] = load <4 x double>, <4 x double>* [[CAST]]
436// CHECK: shufflevector <4 x double> [[LOAD]], <4 x double> undef, <3 x i32> <i32 0, i32 1, i32 2>
437  double sum = fixed;
438  sum = sum + c3.x + c3.y;
439  return sum;
440}
441
442double fixed_3d(__double3 *in) {
443// CHECK: fixed_3d
444// CHECK: call double @args_vec_3d(i32 3, <3 x double>* {{%.*}})
445  return args_vec_3d(3, *in);
446}
447