xref: /llvm-project/clang/test/CodeGen/X86/x86_64-arguments.c (revision 000f2b51633d181bf4a5919fc38cf964a83f2091)
1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -debug-info-kind=limited -Wno-strict-prototypes -o - %s | \
2 // RUN:   FileCheck %s -check-prefix=CHECK -check-prefix=SSE -check-prefix=NO-AVX512
3 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -debug-info-kind=limited -Wno-strict-prototypes -o - %s -target-feature +avx | \
4 // RUN:   FileCheck %s -check-prefix=CHECK -check-prefix=AVX -check-prefix=NO-AVX512
5 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -debug-info-kind=limited -Wno-strict-prototypes -o - %s -target-feature +avx512f | \
6 // RUN:   FileCheck %s -check-prefix=CHECK -check-prefix=AVX -check-prefix=AVX512
7 #include <stdarg.h>
8 
9 // CHECK-LABEL: define{{.*}} signext i8 @f0()
f0(void)10 char f0(void) {
11   return 0;
12 }
13 
14 // CHECK-LABEL: define{{.*}} signext i16 @f1()
f1(void)15 short f1(void) {
16   return 0;
17 }
18 
19 // CHECK-LABEL: define{{.*}} i32 @f2()
f2(void)20 int f2(void) {
21   return 0;
22 }
23 
24 // CHECK-LABEL: define{{.*}} float @f3()
f3(void)25 float f3(void) {
26   return 0;
27 }
28 
29 // CHECK-LABEL: define{{.*}} double @f4()
f4(void)30 double f4(void) {
31   return 0;
32 }
33 
34 // CHECK-LABEL: define{{.*}} x86_fp80 @f5()
f5(void)35 long double f5(void) {
36   return 0;
37 }
38 
39 // CHECK-LABEL: define{{.*}} void @f6(i8 noundef signext %a0, i16 noundef signext %a1, i32 noundef %a2, i64 noundef %a3, ptr noundef %a4)
f6(char a0,short a1,int a2,long long a3,void * a4)40 void f6(char a0, short a1, int a2, long long a3, void *a4) {
41 }
42 
43 // CHECK-LABEL: define{{.*}} void @f7(i32 noundef %a0)
44 typedef enum { A, B, C } e7;
f7(e7 a0)45 void f7(e7 a0) {
46 }
47 
48 // Test merging/passing of upper eightbyte with X87 class.
49 //
50 // CHECK-LABEL: define{{.*}} void @f8_1(ptr dead_on_unwind noalias writable sret(%union.u8) align 16 %agg.result)
51 // CHECK-LABEL: define{{.*}} void @f8_2(ptr noundef byval(%union.u8) align 16 %a0)
52 union u8 {
53   long double a;
54   int b;
55 };
f8_1(void)56 union u8 f8_1(void) { while (1) {} }
f8_2(union u8 a0)57 void f8_2(union u8 a0) {}
58 
59 // CHECK-LABEL: define{{.*}} i64 @f9()
f9(void)60 struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
61 
62 // CHECK-LABEL: define{{.*}} void @f10(i64 %a0.coerce)
63 struct s10 { int a; int b; int : 0; };
f10(struct s10 a0)64 void f10(struct s10 a0) {}
65 
66 // CHECK-LABEL: define{{.*}} void @f11(ptr dead_on_unwind noalias writable sret(%union.anon) align 16 %agg.result)
f11(void)67 union { long double a; float b; } f11(void) { while (1) {} }
68 
69 // CHECK-LABEL: define{{.*}} i32 @f12_0()
70 // CHECK-LABEL: define{{.*}} void @f12_1(i32 %a0.coerce)
71 struct s12 { int a __attribute__((aligned(16))); };
f12_0(void)72 struct s12 f12_0(void) { while (1) {} }
f12_1(struct s12 a0)73 void f12_1(struct s12 a0) {}
74 
75 // Check that sret parameter is accounted for when checking available integer
76 // registers.
77 // CHECK: define{{.*}} void @f13(ptr dead_on_unwind noalias writable sret(%struct.s13_0) align 8 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, ptr noundef byval({{.*}}) align 8 %e, i32 noundef %f)
78 
79 struct s13_0 { long long f0[3]; };
80 struct s13_1 { long long f0[2]; };
f13(int a,int b,int c,int d,struct s13_1 e,int f)81 struct s13_0 f13(int a, int b, int c, int d,
82                  struct s13_1 e, int f) { while (1) {} }
83 
84 // CHECK: define{{.*}} void @f14({{.*}}, i8 noundef signext %X)
f14(int a,int b,int c,int d,int e,int f,char X)85 void f14(int a, int b, int c, int d, int e, int f, char X) {}
86 
87 // CHECK: define{{.*}} void @f15({{.*}}, ptr noundef %X)
f15(int a,int b,int c,int d,int e,int f,void * X)88 void f15(int a, int b, int c, int d, int e, int f, void *X) {}
89 
90 // CHECK: define{{.*}} void @f16({{.*}}, float noundef %X)
f16(float a,float b,float c,float d,float e,float f,float g,float h,float X)91 void f16(float a, float b, float c, float d, float e, float f, float g, float h,
92          float X) {}
93 
94 // CHECK: define{{.*}} void @f17({{.*}}, x86_fp80 noundef %X)
f17(float a,float b,float c,float d,float e,float f,float g,float h,long double X)95 void f17(float a, float b, float c, float d, float e, float f, float g, float h,
96          long double X) {}
97 
98 // Check for valid coercion.  The struct should be passed/returned as i32, not
99 // as i64 for better code quality.
100 // CHECK-LABEL: define{{.*}} void @f18(i32 noundef %a, i32 %f18_arg1.coerce)
101 struct f18_s0 { int f0; };
f18(int a,struct f18_s0 f18_arg1)102 void f18(int a, struct f18_s0 f18_arg1) { while (1) {} }
103 
104 // Check byval alignment.
105 
106 // CHECK-LABEL: define{{.*}} void @f19(ptr noundef byval(%struct.s19) align 16 %x)
107 struct s19 {
108   long double a;
109 };
f19(struct s19 x)110 void f19(struct s19 x) {}
111 
112 // CHECK-LABEL: define{{.*}} void @f20(ptr noundef byval(%struct.s20) align 32 %x)
113 struct __attribute__((aligned(32))) s20 {
114   int x;
115   int y;
116 };
f20(struct s20 x)117 void f20(struct s20 x) {}
118 
119 struct StringRef {
120   long x;
121   const char *Ptr;
122 };
123 
124 // CHECK-LABEL: define{{.*}} ptr @f21(i64 %S.coerce0, ptr %S.coerce1)
f21(struct StringRef S)125 const char *f21(struct StringRef S) { return S.x+S.Ptr; }
126 
127 // PR7567
128 typedef __attribute__ ((aligned(16))) struct f22s { unsigned long long x[2]; } L;
f22(L x,L y)129 void f22(L x, L y) { }
130 // CHECK: @f22
131 // CHECK: %x = alloca{{.*}}, align 16
132 // CHECK: %y = alloca{{.*}}, align 16
133 
134 
135 
136 // PR7714
137 struct f23S {
138   short f0;
139   unsigned f1;
140   int f2;
141 };
142 
143 
f23(int A,struct f23S B)144 void f23(int A, struct f23S B) {
145   // CHECK-LABEL: define{{.*}} void @f23(i32 noundef %A, i64 %B.coerce0, i32 %B.coerce1)
146 }
147 
148 struct f24s { long a; int b; };
149 
f24(struct f23S * X,struct f24s * P2)150 struct f23S f24(struct f23S *X, struct f24s *P2) {
151   return *X;
152 
153   // CHECK: define{{.*}} { i64, i32 } @f24(ptr noundef %X, ptr noundef %P2)
154 }
155 
156 typedef float v4f32 __attribute__((__vector_size__(16)));
f25(v4f32 X)157 v4f32 f25(v4f32 X) {
158   // CHECK-LABEL: define{{.*}} <4 x float> @f25(<4 x float> noundef %X)
159   // CHECK-NOT: alloca
160   // CHECK: alloca <4 x float>
161   // CHECK-NOT: alloca
162   // CHECK: store <4 x float> %X, ptr
163   // CHECK-NOT: store
164   // CHECK: ret <4 x float>
165   return X+X;
166 }
167 
168 struct foo26 {
169   int *X;
170   float *Y;
171 };
172 
f26(struct foo26 * P)173 struct foo26 f26(struct foo26 *P) {
174   // CHECK: define{{.*}} { ptr, ptr } @f26(ptr noundef %P)
175   return *P;
176 }
177 
178 
179 struct v4f32wrapper {
180   v4f32 v;
181 };
182 
f27(struct v4f32wrapper X)183 struct v4f32wrapper f27(struct v4f32wrapper X) {
184   // CHECK-LABEL: define{{.*}} <4 x float> @f27(<4 x float> %X.coerce)
185   return X;
186 }
187 
188 // PR22563 - We should unwrap simple structs and arrays to pass
189 // and return them in the appropriate vector registers if possible.
190 
191 typedef float v8f32 __attribute__((__vector_size__(32)));
192 struct v8f32wrapper {
193   v8f32 v;
194 };
195 
f27a(struct v8f32wrapper X)196 struct v8f32wrapper f27a(struct v8f32wrapper X) {
197   // AVX-LABEL: define{{.*}} <8 x float> @f27a(<8 x float> %X.coerce)
198   return X;
199 }
200 
201 struct v8f32wrapper_wrapper {
202   v8f32 v[1];
203 };
204 
f27b(struct v8f32wrapper_wrapper X)205 struct v8f32wrapper_wrapper f27b(struct v8f32wrapper_wrapper X) {
206   // AVX-LABEL: define{{.*}} <8 x float> @f27b(<8 x float> %X.coerce)
207   return X;
208 }
209 
210 struct f28c {
211   double x;
212   int y;
213 };
f28(struct f28c C)214 void f28(struct f28c C) {
215   // CHECK-LABEL: define{{.*}} void @f28(double %C.coerce0, i32 %C.coerce1)
216 }
217 
218 struct f29a {
219   struct c {
220     double x;
221     int y;
222   } x[1];
223 };
224 
f29a(struct f29a A)225 void f29a(struct f29a A) {
226   // CHECK-LABEL: define{{.*}} void @f29a(double %A.coerce0, i32 %A.coerce1)
227 }
228 
229 struct S0 { char f0[8]; char f2; char f3; char f4; };
f30(struct S0 p_4)230 void f30(struct S0 p_4) {
231   // CHECK-LABEL: define{{.*}} void @f30(i64 %p_4.coerce0, i24 %p_4.coerce1)
232 }
233 
234 // Pass the third element as a float when followed by tail padding.
235 struct f31foo { float a, b, c; };
f31(struct f31foo X)236 float f31(struct f31foo X) {
237   // CHECK-LABEL: define{{.*}} float @f31(<2 x float> %X.coerce0, float %X.coerce1)
238   return X.c;
239 }
240 
f32(_Complex float A,_Complex float B)241 _Complex float f32(_Complex float A, _Complex float B) {
242   // CHECK-LABEL: define{{.*}} <2 x float> @f32(<2 x float> noundef %A.coerce, <2 x float> noundef %B.coerce)
243   return A+B;
244 }
245 
246 struct f33s { long x; float c,d; };
247 
f33(va_list X)248 void f33(va_list X) {
249   va_arg(X, struct f33s);
250 }
251 
252 typedef unsigned long long v1i64 __attribute__((__vector_size__(8)));
253 
254 // CHECK-LABEL: define{{.*}} double @f34(double noundef %arg.coerce)
f34(v1i64 arg)255 v1i64 f34(v1i64 arg) { return arg; }
256 
257 // CHECK-LABEL: define{{.*}} double @f35(double noundef %arg.coerce)
258 typedef unsigned long v1i64_2 __attribute__((__vector_size__(8)));
f35(v1i64_2 arg)259 v1i64_2 f35(v1i64_2 arg) { return arg+arg; }
260 
261 // CHECK: declare void @func(ptr noundef byval(%struct._str) align 16)
262 typedef struct _str {
263   union {
264     long double a;
265     long c;
266   };
267 } str;
268 
269 void func(str s);
270 str ss;
f9122143(void)271 void f9122143(void)
272 {
273   func(ss);
274 }
275 
276 // CHECK-LABEL: define{{.*}} double @f36(double noundef %arg.coerce)
277 typedef unsigned v2i32 __attribute((__vector_size__(8)));
f36(v2i32 arg)278 v2i32 f36(v2i32 arg) { return arg; }
279 
280 // AVX: declare void @f38(<8 x float>)
281 // AVX: declare void @f37(<8 x float> noundef)
282 // SSE: declare void @f38(ptr noundef byval(%struct.s256) align 32)
283 // SSE: declare void @f37(ptr noundef byval(<8 x float>) align 32)
284 typedef float __m256 __attribute__ ((__vector_size__ (32)));
285 typedef struct {
286   __m256 m;
287 } s256;
288 
289 s256 x38;
290 __m256 x37;
291 
292 void f38(s256 x);
293 void f37(__m256 x);
f39(void)294 void f39(void) { f38(x38); f37(x37); }
295 
296 // The two next tests make sure that the struct below is passed
297 // in the same way regardless of avx being used
298 
299 // CHECK: declare void @func40(ptr noundef byval(%struct.t128) align 16)
300 typedef float __m128 __attribute__ ((__vector_size__ (16)));
301 typedef struct t128 {
302   __m128 m;
303   __m128 n;
304 } two128;
305 
306 extern void func40(two128 s);
func41(two128 s)307 void func41(two128 s) {
308   func40(s);
309 }
310 
311 // CHECK: declare void @func42(ptr noundef byval(%struct.t128_2) align 16)
312 typedef struct xxx {
313   __m128 array[2];
314 } Atwo128;
315 typedef struct t128_2 {
316   Atwo128 x;
317 } SA;
318 
319 extern void func42(SA s);
func43(SA s)320 void func43(SA s) {
321   func42(s);
322 }
323 
324 // CHECK-LABEL: define{{.*}} i32 @f44
325 // CHECK: getelementptr inbounds i8, ptr %{{.+}}, i32 31
326 // CHECK-NEXT: call ptr @llvm.ptrmask.p0.i64(ptr %{{[0-9]+}}, i64 -32)
327 typedef int T44 __attribute((vector_size(32)));
328 struct s44 { T44 x; int y; };
f44(int i,...)329 int f44(int i, ...) {
330   __builtin_va_list ap;
331   __builtin_va_start(ap, i);
332   struct s44 s = __builtin_va_arg(ap, struct s44);
333   __builtin_va_end(ap);
334   return s.y;
335 }
336 
337 // Text that vec3 returns the correct LLVM IR type.
338 // AVX-LABEL: define{{.*}} i32 @foo(<3 x i64> noundef %X)
339 typedef long long3 __attribute((ext_vector_type(3)));
foo(long3 X)340 int foo(long3 X)
341 {
342   return 0;
343 }
344 
345 // Make sure we don't use a varargs convention for a function without a
346 // prototype where AVX types are involved.
347 // AVX: @test45
348 // AVX: call i32 @f45
349 int f45();
350 __m256 x45;
test45(void)351 void test45(void) { f45(x45); }
352 
353 // Make sure we use byval to pass 64-bit vectors in memory; the LLVM call
354 // lowering can't handle this case correctly because it runs after legalization.
355 // CHECK: @test46
356 // CHECK: call void @f46({{.*}}ptr noundef byval(<2 x float>) align 8 {{.*}}, ptr noundef byval(<2 x float>) align 8 {{.*}})
357 typedef float v46 __attribute((vector_size(8)));
358 void f46(v46,v46,v46,v46,v46,v46,v46,v46,v46,v46);
test46(void)359 void test46(void) { v46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); }
360 
361 // Check that we pass the struct below without using byval, which helps out
362 // codegen.
363 //
364 // CHECK: @test47
365 // CHECK: call void @f47(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}})
366 struct s47 { unsigned a; };
367 void f47(int,int,int,int,int,int,struct s47);
test47(int a,struct s47 b)368 void test47(int a, struct s47 b) { f47(a, a, a, a, a, a, b); }
369 
370 // In the following example, there are holes in T4 at the 3rd byte and the 4th
371 // byte, however, T2 does not have those holes. T4 is chosen to be the
372 // representing type for union T1, but we can't use load or store of T4 since
373 // it will skip the 3rd byte and the 4th byte.
374 // In general, Since we don't accurately represent the data fields of a union,
375 // do not use load or store of the representing llvm type for the union.
376 typedef _Complex int T2;
377 typedef _Complex char T5;
378 typedef _Complex int T7;
379 typedef struct T4 { T5 field0; T7 field1; } T4;
380 typedef union T1 { T2 field0; T4 field1; } T1;
381 extern T1 T1_retval;
test48(void)382 T1 test48(void) {
383 // CHECK: @test48
384 // CHECK: memcpy
385 // CHECK: memcpy
386   return T1_retval;
387 }
388 
389 void test49_helper(double, ...);
test49(double d,double e)390 void test49(double d, double e) {
391   test49_helper(d, e);
392 }
393 // CHECK-LABEL:    define{{.*}} void @test49(
394 // CHECK:      [[T0:%.*]] = load double, ptr
395 // CHECK-NEXT: [[T1:%.*]] = load double, ptr
396 // CHECK-NEXT: call void (double, ...) @test49_helper(double noundef [[T0]], double noundef [[T1]])
397 
398 void test50_helper();
test50(double d,double e)399 void test50(double d, double e) {
400   test50_helper(d, e);
401 }
402 // CHECK-LABEL:    define{{.*}} void @test50(
403 // CHECK:      [[T0:%.*]] = load double, ptr
404 // CHECK-NEXT: [[T1:%.*]] = load double, ptr
405 // CHECK-NEXT: call void (double, double, ...) @test50_helper(double noundef [[T0]], double noundef [[T1]])
406 
407 struct test51_s { __uint128_t intval; };
test51(struct test51_s * s,__builtin_va_list argList)408 void test51(struct test51_s *s, __builtin_va_list argList) {
409     *s = __builtin_va_arg(argList, struct test51_s);
410 }
411 
412 // CHECK-LABEL: define{{.*}} void @test51
413 // CHECK: [[TMP_ADDR:%.*]] = alloca [[STRUCT_TEST51:%.*]], align 16
414 // CHECK: br i1
415 // CHECK: [[REG_SAVE_AREA_PTR:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 3
416 // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[REG_SAVE_AREA_PTR]]
417 // CHECK-NEXT: [[VALUE_ADDR:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 {{.*}}
418 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP_ADDR]], ptr align 8 [[VALUE_ADDR]], i64 16, i1 false)
419 // CHECK-NEXT: add i32 {{.*}}, 16
420 // CHECK-NEXT: store i32 {{.*}}, ptr {{.*}}
421 // CHECK-NEXT: br label
422 
423 void test52_helper(int, ...);
424 __m256 x52;
test52(void)425 void test52(void) {
426   test52_helper(0, x52, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
427 }
428 // AVX: @test52_helper(i32 noundef 0, <8 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef {{%[a-zA-Z0-9]+}}, double noundef {{%[a-zA-Z0-9]+}})
429 
test53(__m256 * m,__builtin_va_list argList)430 void test53(__m256 *m, __builtin_va_list argList) {
431   *m = __builtin_va_arg(argList, __m256);
432 }
433 // AVX-LABEL: define{{.*}} void @test53
434 // AVX-NOT: br i1
435 // AVX: ret void
436 
437 void test54_helper(__m256, ...);
438 __m256 x54;
test54(void)439 void test54(void) {
440   test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
441   test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
442 }
443 // AVX: @test54_helper(<8 x float> noundef {{%[a-zA-Z0-9]+}}, <8 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef {{%[a-zA-Z0-9]+}}, double noundef {{%[a-zA-Z0-9]+}})
444 // AVX: @test54_helper(<8 x float> noundef {{%[a-zA-Z0-9]+}}, <8 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, ptr noundef byval({ double, double }) align 8 {{%[^)]+}})
445 
446 typedef float __m512 __attribute__ ((__vector_size__ (64)));
447 typedef struct {
448   __m512 m;
449 } s512;
450 
451 s512 x55;
452 __m512 x56;
453 
454 // On AVX512, aggregates which contain a __m512 type are classified as SSE/SSEUP
455 // as per https://github.com/hjl-tools/x86-psABI/commit/30f9c9 3.2.3p2 Rule 1
456 //
457 // AVX512: declare void @f55(<16 x float>)
458 // NO-AVX512: declare void @f55(ptr noundef byval(%struct.s512) align 64)
459 void f55(s512 x);
460 
461 // __m512 has type SSE/SSEUP on AVX512.
462 //
463 // AVX512: declare void @f56(<16 x float> noundef)
464 // NO-AVX512: declare void @f56(ptr noundef byval(<16 x float>) align 64)
465 void f56(__m512 x);
f57(void)466 void f57(void) { f55(x55); f56(x56); }
467 
468 // Like for __m128 on AVX, check that the struct below is passed
469 // in the same way regardless of AVX512 being used.
470 //
471 // CHECK: declare void @f58(ptr noundef byval(%struct.t256) align 32)
472 typedef struct t256 {
473   __m256 m;
474   __m256 n;
475 } two256;
476 
477 extern void f58(two256 s);
f59(two256 s)478 void f59(two256 s) {
479   f58(s);
480 }
481 
482 // CHECK: declare void @f60(ptr noundef byval(%struct.sat256) align 32)
483 typedef struct at256 {
484   __m256 array[2];
485 } Atwo256;
486 typedef struct sat256 {
487   Atwo256 x;
488 } SAtwo256;
489 
490 extern void f60(SAtwo256 s);
f61(SAtwo256 s)491 void f61(SAtwo256 s) {
492   f60(s);
493 }
494 
495 // AVX512: @f62_helper(i32 noundef 0, <16 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef {{%[a-zA-Z0-9]+}}, double noundef {{%[a-zA-Z0-9]+}})
496 void f62_helper(int, ...);
497 __m512 x62;
f62(void)498 void f62(void) {
499   f62_helper(0, x62, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
500 }
501 
502 // Like for __m256 on AVX, we always pass __m512 in memory, and don't
503 // need to use the register save area.
504 //
505 // AVX512-LABEL: define{{.*}} void @f63
506 // AVX512-NOT: br i1
507 // AVX512: ret void
f63(__m512 * m,__builtin_va_list argList)508 void f63(__m512 *m, __builtin_va_list argList) {
509   *m = __builtin_va_arg(argList, __m512);
510 }
511 
512 // AVX512: @f64_helper(<16 x float> noundef {{%[a-zA-Z0-9]+}}, <16 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef {{%[a-zA-Z0-9]+}}, double noundef {{%[a-zA-Z0-9]+}})
513 // AVX512: @f64_helper(<16 x float> noundef {{%[a-zA-Z0-9]+}}, <16 x float> noundef {{%[a-zA-Z0-9]+}}, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, double noundef 1.000000e+00, ptr noundef byval({ double, double }) align 8 {{%[^)]+}})
514 void f64_helper(__m512, ...);
515 __m512 x64;
f64(void)516 void f64(void) {
517   f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
518   f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
519 }
520 
521 struct t65 {
522   __m256 m;
523   int : 0;
524 };
525 // SSE-LABEL: @f65(ptr noundef byval(%struct.t65) align 32 %{{[^,)]+}})
526 // AVX: @f65(<8 x float> %{{[^,)]+}})
f65(struct t65 a0)527 void f65(struct t65 a0) {
528 }
529 
530 typedef float t66 __attribute__((__vector_size__(128), __aligned__(128)));
531 
532 // AVX512: @f66(ptr noundef byval(<32 x float>) align 128 %0)
f66(t66 a0)533 void f66(t66 a0) {
534 }
535 
536 typedef long long t67 __attribute__((aligned (4)));
537 struct s67 {
538   int a;
539   t67 b;
540 };
541 // CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 %x)
f67(struct s67 x)542 void f67(struct s67 x) {
543 }
544 
545 typedef double t68 __attribute__((aligned (4)));
546 struct s68 {
547   int a;
548   t68 b;
549 };
550 // CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x)
f68(struct s68 x)551 void f68(struct s68 x) {
552 }
553 
554 /// The synthesized __va_list_tag does not have file/line fields.
555 // CHECK:      = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__va_list_tag",
556 // CHECK-NOT:  file:
557 // CHECK-NOT:  line:
558 // CHECK-SAME: size:
559