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