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() 6char f0(void) { 7 return 0; 8} 9 10// CHECK-LABEL: define signext i16 @f1() 11short f1(void) { 12 return 0; 13} 14 15// CHECK-LABEL: define i32 @f2() 16int f2(void) { 17 return 0; 18} 19 20// CHECK-LABEL: define float @f3() 21float f3(void) { 22 return 0; 23} 24 25// CHECK-LABEL: define double @f4() 26double f4(void) { 27 return 0; 28} 29 30// CHECK-LABEL: define x86_fp80 @f5() 31long 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) 36void f6(char a0, short a1, int a2, long long a3, void *a4) { 37} 38 39// CHECK-LABEL: 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-LABEL: define void @f8_1(%union.u8* noalias sret %agg.result) 47// CHECK-LABEL: 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-LABEL: define i64 @f9() 56struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} } 57 58// CHECK-LABEL: define void @f10(i64 %a0.coerce) 59struct s10 { int a; int b; int : 0; }; 60void f10(struct s10 a0) {} 61 62// CHECK-LABEL: define void @f11(%union.anon* noalias sret %agg.result) 63union { 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) 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-LABEL: 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-LABEL: define void @f19(%struct.s19* byval align 16 %x) 104struct s19 { 105 long double a; 106}; 107void f19(struct s19 x) {} 108 109// CHECK-LABEL: 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-LABEL: 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-LABEL: 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-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 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-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 190typedef float v8f32 __attribute__((__vector_size__(32))); 191struct v8f32wrapper { 192 v8f32 v; 193}; 194 195struct v8f32wrapper f27a(struct v8f32wrapper X) { 196 // AVX-LABEL: define <8 x float> @f27a(<8 x float> %X.coerce) 197 return X; 198} 199 200struct v8f32wrapper_wrapper { 201 v8f32 v[1]; 202}; 203 204struct 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 210struct f28c { 211 double x; 212 int y; 213}; 214void f28(struct f28c C) { 215 // CHECK-LABEL: define void @f28(double %C.coerce0, i32 %C.coerce1) 216} 217 218struct f29a { 219 struct c { 220 double x; 221 int y; 222 } x[1]; 223}; 224 225void f29a(struct f29a A) { 226 // CHECK-LABEL: define void @f29a(double %A.coerce0, i32 %A.coerce1) 227} 228 229// rdar://8249586 230struct S0 { char f0[8]; char f2; char f3; char f4; }; 231void 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 237struct f31foo { float a, b, c; }; 238float f31(struct f31foo X) { 239 // CHECK-LABEL: define float @f31(<2 x float> %X.coerce0, float %X.coerce1) 240 return X.c; 241} 242 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 251struct f33s { long x; float c,d; }; 252 253void f33(va_list X) { 254 va_arg(X, struct f33s); 255} 256 257typedef unsigned long long v1i64 __attribute__((__vector_size__(8))); 258 259// rdar://8359248 260// CHECK-LABEL: define i64 @f34(i64 %arg.coerce) 261v1i64 f34(v1i64 arg) { return arg; } 262 263 264// rdar://8358475 265// CHECK-LABEL: define i64 @f35(i64 %arg.coerce) 266typedef unsigned long v1i64_2 __attribute__((__vector_size__(8))); 267v1i64_2 f35(v1i64_2 arg) { return arg+arg; } 268 269// rdar://9122143 270// CHECK: declare void @func(%struct._str* byval align 16) 271typedef struct _str { 272 union { 273 long double a; 274 long c; 275 }; 276} str; 277 278void func(str s); 279str ss; 280void f9122143() 281{ 282 func(ss); 283} 284 285// CHECK-LABEL: define double @f36(double %arg.coerce) 286typedef unsigned v2i32 __attribute((__vector_size__(8))); 287v2i32 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) 293typedef float __m256 __attribute__ ((__vector_size__ (32))); 294typedef struct { 295 __m256 m; 296} s256; 297 298s256 x38; 299__m256 x37; 300 301void f38(s256 x); 302void f37(__m256 x); 303void 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) 309typedef float __m128 __attribute__ ((__vector_size__ (16))); 310typedef struct t128 { 311 __m128 m; 312 __m128 n; 313} two128; 314 315extern void func40(two128 s); 316void func41(two128 s) { 317 func40(s); 318} 319 320// CHECK: declare void @func42(%struct.t128_2* byval align 16) 321typedef struct xxx { 322 __m128 array[2]; 323} Atwo128; 324typedef struct t128_2 { 325 Atwo128 x; 326} SA; 327 328extern void func42(SA s); 329void 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 337typedef int T44 __attribute((vector_size(32))); 338struct s44 { T44 x; int y; }; 339int 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) 349typedef long long3 __attribute((ext_vector_type(3))); 350int 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>)*) 359int f45(); 360__m256 x45; 361void 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 {{.*}}) 367typedef float v46 __attribute((vector_size(8))); 368void f46(v46,v46,v46,v46,v46,v46,v46,v46,v46,v46); 369void 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 {{.*}}) 376struct s47 { unsigned a; }; 377void f47(int,int,int,int,int,int,struct s47); 378void 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. 387typedef _Complex int T2; 388typedef _Complex char T5; 389typedef _Complex int T7; 390typedef struct T4 { T5 field0; T7 field1; } T4; 391typedef union T1 { T2 field0; T4 field1; } T1; 392extern T1 T1_retval; 393T1 test48(void) { 394// CHECK: @test48 395// CHECK: memcpy 396// CHECK: memcpy 397 return T1_retval; 398} 399 400void test49_helper(double, ...); 401void test49(double d, double e) { 402 test49_helper(d, e); 403} 404// CHECK-LABEL: define void @test49( 405// CHECK: [[T0:%.*]] = load double, double* 406// CHECK-NEXT: [[T1:%.*]] = load double, double* 407// CHECK-NEXT: call void (double, ...) @test49_helper(double [[T0]], double [[T1]]) 408 409void test50_helper(); 410void test50(double d, double e) { 411 test50_helper(d, e); 412} 413// CHECK-LABEL: define void @test50( 414// CHECK: [[T0:%.*]] = load double, double* 415// CHECK-NEXT: [[T1:%.*]] = load double, double* 416// CHECK-NEXT: call void (double, double, ...) bitcast (void (...)* @test50_helper to void (double, double, ...)*)(double [[T0]], double [[T1]]) 417 418struct test51_s { __uint128_t intval; }; 419void 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*, i8** [[REG_SAVE_AREA_PTR]] 428// CHECK-NEXT: [[VALUE_ADDR:%.*]] = getelementptr i8, 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 437void test52_helper(int, ...); 438__m256 x52; 439void 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 444void 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 451void test54_helper(__m256, ...); 452__m256 x54; 453void 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