1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s| FileCheck %s
2 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -target-feature +avx | FileCheck %s -check-prefix=AVX
3 #include <stdarg.h>
4
5 // CHECK-LABEL: define signext i8 @f0()
f0(void)6 char f0(void) {
7 return 0;
8 }
9
10 // CHECK-LABEL: define signext i16 @f1()
f1(void)11 short f1(void) {
12 return 0;
13 }
14
15 // CHECK-LABEL: define i32 @f2()
f2(void)16 int f2(void) {
17 return 0;
18 }
19
20 // CHECK-LABEL: define float @f3()
f3(void)21 float f3(void) {
22 return 0;
23 }
24
25 // CHECK-LABEL: define double @f4()
f4(void)26 double f4(void) {
27 return 0;
28 }
29
30 // CHECK-LABEL: define x86_fp80 @f5()
f5(void)31 long double f5(void) {
32 return 0;
33 }
34
35 // CHECK-LABEL: define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8* %a4)
f6(char a0,short a1,int a2,long long a3,void * a4)36 void f6(char a0, short a1, int a2, long long a3, void *a4) {
37 }
38
39 // CHECK-LABEL: define void @f7(i32 %a0)
40 typedef enum { A, B, C } e7;
f7(e7 a0)41 void f7(e7 a0) {
42 }
43
44 // Test merging/passing of upper eightbyte with X87 class.
45 //
46 // CHECK-LABEL: define void @f8_1(%union.u8* noalias sret %agg.result)
47 // CHECK-LABEL: define void @f8_2(%union.u8* byval align 16 %a0)
48 union u8 {
49 long double a;
50 int b;
51 };
f8_1()52 union u8 f8_1() { while (1) {} }
f8_2(union u8 a0)53 void f8_2(union u8 a0) {}
54
55 // CHECK-LABEL: define i64 @f9()
f9(void)56 struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
57
58 // CHECK-LABEL: define void @f10(i64 %a0.coerce)
59 struct s10 { int a; int b; int : 0; };
f10(struct s10 a0)60 void f10(struct s10 a0) {}
61
62 // CHECK-LABEL: define void @f11(%union.anon* noalias sret %agg.result)
f11()63 union { long double a; float b; } f11() { while (1) {} }
64
65 // CHECK-LABEL: define i32 @f12_0()
66 // CHECK-LABEL: define void @f12_1(i32 %a0.coerce)
67 struct s12 { int a __attribute__((aligned(16))); };
f12_0(void)68 struct s12 f12_0(void) { while (1) {} }
f12_1(struct s12 a0)69 void f12_1(struct s12 a0) {}
70
71 // Check that sret parameter is accounted for when checking available integer
72 // registers.
73 // CHECK: define void @f13(%struct.s13_0* noalias sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, {{.*}}* byval align 8 %e, i32 %f)
74
75 struct s13_0 { long long f0[3]; };
76 struct s13_1 { long long f0[2]; };
f13(int a,int b,int c,int d,struct s13_1 e,int f)77 struct s13_0 f13(int a, int b, int c, int d,
78 struct s13_1 e, int f) { while (1) {} }
79
80 // CHECK: define void @f14({{.*}}, i8 signext %X)
f14(int a,int b,int c,int d,int e,int f,char X)81 void f14(int a, int b, int c, int d, int e, int f, char X) {}
82
83 // CHECK: define void @f15({{.*}}, i8* %X)
f15(int a,int b,int c,int d,int e,int f,void * X)84 void f15(int a, int b, int c, int d, int e, int f, void *X) {}
85
86 // CHECK: define void @f16({{.*}}, float %X)
f16(float a,float b,float c,float d,float e,float f,float g,float h,float X)87 void f16(float a, float b, float c, float d, float e, float f, float g, float h,
88 float X) {}
89
90 // CHECK: define void @f17({{.*}}, x86_fp80 %X)
f17(float a,float b,float c,float d,float e,float f,float g,float h,long double X)91 void f17(float a, float b, float c, float d, float e, float f, float g, float h,
92 long double X) {}
93
94 // Check for valid coercion. The struct should be passed/returned as i32, not
95 // as i64 for better code quality.
96 // rdar://8135035
97 // CHECK-LABEL: define void @f18(i32 %a, i32 %f18_arg1.coerce)
98 struct f18_s0 { int f0; };
f18(int a,struct f18_s0 f18_arg1)99 void f18(int a, struct f18_s0 f18_arg1) { while (1) {} }
100
101 // Check byval alignment.
102
103 // CHECK-LABEL: define void @f19(%struct.s19* byval align 16 %x)
104 struct s19 {
105 long double a;
106 };
f19(struct s19 x)107 void f19(struct s19 x) {}
108
109 // CHECK-LABEL: define void @f20(%struct.s20* byval align 32 %x)
110 struct __attribute__((aligned(32))) s20 {
111 int x;
112 int y;
113 };
f20(struct s20 x)114 void f20(struct s20 x) {}
115
116 struct StringRef {
117 long x;
118 const char *Ptr;
119 };
120
121 // rdar://7375902
122 // CHECK-LABEL: define i8* @f21(i64 %S.coerce0, i8* %S.coerce1)
f21(struct StringRef S)123 const char *f21(struct StringRef S) { return S.x+S.Ptr; }
124
125 // PR7567
126 typedef __attribute__ ((aligned(16))) struct f22s { unsigned long long x[2]; } L;
f22(L x,L y)127 void f22(L x, L y) { }
128 // CHECK: @f22
129 // CHECK: %x = alloca{{.*}}, align 16
130 // CHECK: %y = alloca{{.*}}, align 16
131
132
133
134 // PR7714
135 struct f23S {
136 short f0;
137 unsigned f1;
138 int f2;
139 };
140
141
f23(int A,struct f23S B)142 void f23(int A, struct f23S B) {
143 // CHECK-LABEL: define void @f23(i32 %A, i64 %B.coerce0, i32 %B.coerce1)
144 }
145
146 struct f24s { long a; int b; };
147
f24(struct f23S * X,struct f24s * P2)148 struct f23S f24(struct f23S *X, struct f24s *P2) {
149 return *X;
150
151 // CHECK: define { i64, i32 } @f24(%struct.f23S* %X, %struct.f24s* %P2)
152 }
153
154 // rdar://8248065
155 typedef float v4f32 __attribute__((__vector_size__(16)));
f25(v4f32 X)156 v4f32 f25(v4f32 X) {
157 // CHECK-LABEL: define <4 x float> @f25(<4 x float> %X)
158 // CHECK-NOT: alloca
159 // CHECK: alloca <4 x float>
160 // CHECK-NOT: alloca
161 // CHECK: store <4 x float> %X, <4 x float>*
162 // CHECK-NOT: store
163 // CHECK: ret <4 x float>
164 return X+X;
165 }
166
167 struct foo26 {
168 int *X;
169 float *Y;
170 };
171
f26(struct foo26 * P)172 struct foo26 f26(struct foo26 *P) {
173 // CHECK: define { i32*, float* } @f26(%struct.foo26* %P)
174 return *P;
175 }
176
177
178 struct v4f32wrapper {
179 v4f32 v;
180 };
181
f27(struct v4f32wrapper X)182 struct v4f32wrapper f27(struct v4f32wrapper X) {
183 // CHECK-LABEL: define <4 x float> @f27(<4 x float> %X.coerce)
184 return X;
185 }
186
187 // PR22563 - We should unwrap simple structs and arrays to pass
188 // and return them in the appropriate vector registers if possible.
189
190 typedef float v8f32 __attribute__((__vector_size__(32)));
191 struct v8f32wrapper {
192 v8f32 v;
193 };
194
f27a(struct v8f32wrapper X)195 struct v8f32wrapper f27a(struct v8f32wrapper X) {
196 // AVX-LABEL: define <8 x float> @f27a(<8 x float> %X.coerce)
197 return X;
198 }
199
200 struct v8f32wrapper_wrapper {
201 v8f32 v[1];
202 };
203
f27b(struct v8f32wrapper_wrapper X)204 struct v8f32wrapper_wrapper f27b(struct v8f32wrapper_wrapper X) {
205 // AVX-LABEL: define <8 x float> @f27b(<8 x float> %X.coerce)
206 return X;
207 }
208
209 // rdar://5711709
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 // rdar://8249586
230 struct S0 { char f0[8]; char f2; char f3; char f4; };
f30(struct S0 p_4)231 void f30(struct S0 p_4) {
232 // CHECK-LABEL: define void @f30(i64 %p_4.coerce0, i24 %p_4.coerce1)
233 }
234
235 // Pass the third element as a float when followed by tail padding.
236 // rdar://8251384
237 struct f31foo { float a, b, c; };
f31(struct f31foo X)238 float f31(struct f31foo X) {
239 // CHECK-LABEL: define float @f31(<2 x float> %X.coerce0, float %X.coerce1)
240 return X.c;
241 }
242
f32(_Complex float A,_Complex float B)243 _Complex float f32(_Complex float A, _Complex float B) {
244 // rdar://6379669
245 // CHECK-LABEL: define <2 x float> @f32(<2 x float> %A.coerce, <2 x float> %B.coerce)
246 return A+B;
247 }
248
249
250 // rdar://8357396
251 struct f33s { long x; float c,d; };
252
f33(va_list X)253 void f33(va_list X) {
254 va_arg(X, struct f33s);
255 }
256
257 typedef unsigned long long v1i64 __attribute__((__vector_size__(8)));
258
259 // rdar://8359248
260 // CHECK-LABEL: define i64 @f34(i64 %arg.coerce)
f34(v1i64 arg)261 v1i64 f34(v1i64 arg) { return arg; }
262
263
264 // rdar://8358475
265 // CHECK-LABEL: define i64 @f35(i64 %arg.coerce)
266 typedef unsigned long v1i64_2 __attribute__((__vector_size__(8)));
f35(v1i64_2 arg)267 v1i64_2 f35(v1i64_2 arg) { return arg+arg; }
268
269 // rdar://9122143
270 // CHECK: declare void @func(%struct._str* byval align 16)
271 typedef struct _str {
272 union {
273 long double a;
274 long c;
275 };
276 } str;
277
278 void func(str s);
279 str ss;
f9122143()280 void f9122143()
281 {
282 func(ss);
283 }
284
285 // CHECK-LABEL: define double @f36(double %arg.coerce)
286 typedef unsigned v2i32 __attribute((__vector_size__(8)));
f36(v2i32 arg)287 v2i32 f36(v2i32 arg) { return arg; }
288
289 // AVX: declare void @f38(<8 x float>)
290 // AVX: declare void @f37(<8 x float>)
291 // CHECK: declare void @f38(%struct.s256* byval align 32)
292 // CHECK: declare void @f37(<8 x float>* byval align 32)
293 typedef float __m256 __attribute__ ((__vector_size__ (32)));
294 typedef struct {
295 __m256 m;
296 } s256;
297
298 s256 x38;
299 __m256 x37;
300
301 void f38(s256 x);
302 void f37(__m256 x);
f39()303 void f39() { f38(x38); f37(x37); }
304
305 // The two next tests make sure that the struct below is passed
306 // in the same way regardless of avx being used
307
308 // CHECK: declare void @func40(%struct.t128* byval align 16)
309 typedef float __m128 __attribute__ ((__vector_size__ (16)));
310 typedef struct t128 {
311 __m128 m;
312 __m128 n;
313 } two128;
314
315 extern void func40(two128 s);
func41(two128 s)316 void func41(two128 s) {
317 func40(s);
318 }
319
320 // CHECK: declare void @func42(%struct.t128_2* byval align 16)
321 typedef struct xxx {
322 __m128 array[2];
323 } Atwo128;
324 typedef struct t128_2 {
325 Atwo128 x;
326 } SA;
327
328 extern void func42(SA s);
func43(SA s)329 void func43(SA s) {
330 func42(s);
331 }
332
333 // CHECK-LABEL: define i32 @f44
334 // CHECK: ptrtoint
335 // CHECK-NEXT: and {{.*}}, -32
336 // CHECK-NEXT: inttoptr
337 typedef int T44 __attribute((vector_size(32)));
338 struct s44 { T44 x; int y; };
f44(int i,...)339 int f44(int i, ...) {
340 __builtin_va_list ap;
341 __builtin_va_start(ap, i);
342 struct s44 s = __builtin_va_arg(ap, struct s44);
343 __builtin_va_end(ap);
344 return s.y;
345 }
346
347 // Text that vec3 returns the correct LLVM IR type.
348 // AVX-LABEL: define i32 @foo(<3 x i64> %X)
349 typedef long long3 __attribute((ext_vector_type(3)));
foo(long3 X)350 int foo(long3 X)
351 {
352 return 0;
353 }
354
355 // Make sure we don't use a varargs convention for a function without a
356 // prototype where AVX types are involved.
357 // AVX: @test45
358 // AVX: call i32 bitcast (i32 (...)* @f45 to i32 (<8 x float>)*)
359 int f45();
360 __m256 x45;
test45()361 void test45() { f45(x45); }
362
363 // Make sure we use byval to pass 64-bit vectors in memory; the LLVM call
364 // lowering can't handle this case correctly because it runs after legalization.
365 // CHECK: @test46
366 // CHECK: call void @f46({{.*}}<2 x float>* byval align 8 {{.*}}, <2 x float>* byval align 8 {{.*}})
367 typedef float v46 __attribute((vector_size(8)));
368 void f46(v46,v46,v46,v46,v46,v46,v46,v46,v46,v46);
test46()369 void test46() { v46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); }
370
371 // Check that we pass the struct below without using byval, which helps out
372 // codegen.
373 //
374 // CHECK: @test47
375 // CHECK: call void @f47(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}})
376 struct s47 { unsigned a; };
377 void f47(int,int,int,int,int,int,struct s47);
test47(int a,struct s47 b)378 void test47(int a, struct s47 b) { f47(a, a, a, a, a, a, b); }
379
380 // rdar://12723368
381 // In the following example, there are holes in T4 at the 3rd byte and the 4th
382 // byte, however, T2 does not have those holes. T4 is chosen to be the
383 // representing type for union T1, but we can't use load or store of T4 since
384 // it will skip the 3rd byte and the 4th byte.
385 // In general, Since we don't accurately represent the data fields of a union,
386 // do not use load or store of the representing llvm type for the union.
387 typedef _Complex int T2;
388 typedef _Complex char T5;
389 typedef _Complex int T7;
390 typedef struct T4 { T5 field0; T7 field1; } T4;
391 typedef union T1 { T2 field0; T4 field1; } T1;
392 extern T1 T1_retval;
test48(void)393 T1 test48(void) {
394 // CHECK: @test48
395 // CHECK: memcpy
396 // CHECK: memcpy
397 return T1_retval;
398 }
399
400 void test49_helper(double, ...);
test49(double d,double e)401 void test49(double d, double e) {
402 test49_helper(d, e);
403 }
404 // CHECK-LABEL: define void @test49(
405 // CHECK: [[T0:%.*]] = load double*
406 // CHECK-NEXT: [[T1:%.*]] = load double*
407 // CHECK-NEXT: call void (double, ...)* @test49_helper(double [[T0]], double [[T1]])
408
409 void test50_helper();
test50(double d,double e)410 void test50(double d, double e) {
411 test50_helper(d, e);
412 }
413 // CHECK-LABEL: define void @test50(
414 // CHECK: [[T0:%.*]] = load double*
415 // CHECK-NEXT: [[T1:%.*]] = load double*
416 // CHECK-NEXT: call void (double, double, ...)* bitcast (void (...)* @test50_helper to void (double, double, ...)*)(double [[T0]], double [[T1]])
417
418 struct test51_s { __uint128_t intval; };
test51(struct test51_s * s,__builtin_va_list argList)419 void test51(struct test51_s *s, __builtin_va_list argList) {
420 *s = __builtin_va_arg(argList, struct test51_s);
421 }
422
423 // CHECK-LABEL: define void @test51
424 // CHECK: [[TMP_ADDR:%.*]] = alloca [[STRUCT_TEST51:%.*]], align 16
425 // CHECK: br i1
426 // CHECK: [[REG_SAVE_AREA_PTR:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 3
427 // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load i8** [[REG_SAVE_AREA_PTR]]
428 // CHECK-NEXT: [[VALUE_ADDR:%.*]] = getelementptr i8* [[REG_SAVE_AREA]], i32 {{.*}}
429 // CHECK-NEXT: [[CASTED_VALUE_ADDR:%.*]] = bitcast i8* [[VALUE_ADDR]] to [[STRUCT_TEST51]]
430 // CHECK-NEXT: [[CASTED_TMP_ADDR:%.*]] = bitcast [[STRUCT_TEST51]]* [[TMP_ADDR]] to i8*
431 // CHECK-NEXT: [[RECASTED_VALUE_ADDR:%.*]] = bitcast [[STRUCT_TEST51]]* [[CASTED_VALUE_ADDR]] to i8*
432 // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[CASTED_TMP_ADDR]], i8* [[RECASTED_VALUE_ADDR]], i64 16, i32 8, i1 false)
433 // CHECK-NEXT: add i32 {{.*}}, 16
434 // CHECK-NEXT: store i32 {{.*}}, i32* {{.*}}
435 // CHECK-NEXT: br label
436
437 void test52_helper(int, ...);
438 __m256 x52;
test52()439 void test52() {
440 test52_helper(0, x52, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
441 }
442 // AVX: @test52_helper(i32 0, <8 x float> {{%[a-zA-Z0-9]+}}, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double {{%[a-zA-Z0-9]+}}, double {{%[a-zA-Z0-9]+}})
443
test53(__m256 * m,__builtin_va_list argList)444 void test53(__m256 *m, __builtin_va_list argList) {
445 *m = __builtin_va_arg(argList, __m256);
446 }
447 // AVX-LABEL: define void @test53
448 // AVX-NOT: br i1
449 // AVX: ret void
450
451 void test54_helper(__m256, ...);
452 __m256 x54;
test54()453 void test54() {
454 test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
455 test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
456 }
457 // AVX: @test54_helper(<8 x float> {{%[a-zA-Z0-9]+}}, <8 x float> {{%[a-zA-Z0-9]+}}, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double {{%[a-zA-Z0-9]+}}, double {{%[a-zA-Z0-9]+}})
458 // AVX: @test54_helper(<8 x float> {{%[a-zA-Z0-9]+}}, <8 x float> {{%[a-zA-Z0-9]+}}, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, { double, double }* byval align 8 {{%[a-zA-Z0-9]+}})
459