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