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