Reid Kleckner | 80944df | 2014-10-31 22:00:51 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s |
| 2 | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=X64 |
| 3 | |
| 4 | void __vectorcall v1(int a, int b) {} |
| 5 | // CHECK: define x86_vectorcallcc void @"\01v1@@8"(i32 inreg %a, i32 inreg %b) |
| 6 | // X64: define x86_vectorcallcc void @"\01v1@@16"(i32 %a, i32 %b) |
| 7 | |
| 8 | void __vectorcall v2(char a, char b) {} |
| 9 | // CHECK: define x86_vectorcallcc void @"\01v2@@8"(i8 inreg signext %a, i8 inreg signext %b) |
| 10 | // X64: define x86_vectorcallcc void @"\01v2@@16"(i8 %a, i8 %b) |
| 11 | |
| 12 | struct Small { int a; }; |
| 13 | void __vectorcall v3(int a, struct Small b, int c) {} |
| 14 | // CHECK: define x86_vectorcallcc void @"\01v3@@12"(i32 inreg %a, %struct.Small* byval align 4 %b, i32 inreg %c) |
| 15 | // X64: define x86_vectorcallcc void @"\01v3@@24"(i32 %a, i32 %b.coerce, i32 %c) |
| 16 | |
| 17 | struct Large { int a[5]; }; |
| 18 | void __vectorcall v4(int a, struct Large b, int c) {} |
| 19 | // CHECK: define x86_vectorcallcc void @"\01v4@@28"(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c) |
| 20 | // X64: define x86_vectorcallcc void @"\01v4@@40"(i32 %a, %struct.Large* %b, i32 %c) |
| 21 | |
| 22 | struct HFA2 { double x, y; }; |
| 23 | struct HFA4 { double w, x, y, z; }; |
| 24 | struct HFA5 { double v, w, x, y, z; }; |
| 25 | |
| 26 | void __vectorcall hfa1(int a, struct HFA4 b, int c) {} |
| 27 | // CHECK: define x86_vectorcallcc void @"\01hfa1@@40"(i32 inreg %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 inreg %c) |
| 28 | // X64: define x86_vectorcallcc void @"\01hfa1@@48"(i32 %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 %c) |
| 29 | |
| 30 | // HFAs that would require more than six total SSE registers are passed |
| 31 | // indirectly. Additional vector arguments can consume the rest of the SSE |
| 32 | // registers. |
| 33 | void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} |
| 34 | // CHECK: define x86_vectorcallcc void @"\01hfa2@@72"(double %a.0, double %a.1, double %a.2, double %a.3, %struct.HFA4* inreg %b, double %c) |
| 35 | // X64: define x86_vectorcallcc void @"\01hfa2@@72"(double %a.0, double %a.1, double %a.2, double %a.3, %struct.HFA4* align 8 %b, double %c) |
| 36 | |
| 37 | // Ensure that we pass builtin types directly while counting them against the |
| 38 | // SSE register usage. |
| 39 | void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {} |
| 40 | // CHECK: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* inreg %f) |
| 41 | // X64: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* align 8 %f) |
| 42 | |
| 43 | // Aggregates with more than four elements are not HFAs and are passed byval. |
| 44 | // Because they are not classified as homogeneous, they don't get special |
| 45 | // handling to ensure alignment. |
| 46 | void __vectorcall hfa4(struct HFA5 a) {} |
| 47 | // CHECK: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* byval align 4) |
| 48 | // X64: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* %a) |
| 49 | |
| 50 | // Return HFAs of 4 or fewer elements in registers. |
| 51 | static struct HFA2 g_hfa2; |
| 52 | struct HFA2 __vectorcall hfa5(void) { return g_hfa2; } |
| 53 | // CHECK: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"() |
| 54 | // X64: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"() |
| 55 | |
| 56 | typedef float __attribute__((vector_size(16))) v4f32; |
| 57 | struct HVA2 { v4f32 x, y; }; |
| 58 | struct HVA4 { v4f32 w, x, y, z; }; |
| 59 | |
| 60 | void __vectorcall hva1(int a, struct HVA4 b, int c) {} |
| 61 | // CHECK: define x86_vectorcallcc void @"\01hva1@@72"(i32 inreg %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 inreg %c) |
| 62 | // X64: define x86_vectorcallcc void @"\01hva1@@80"(i32 %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 %c) |
| 63 | |
| 64 | void __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {} |
| 65 | // CHECK: define x86_vectorcallcc void @"\01hva2@@144"(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, %struct.HVA4* inreg %b, <4 x float> %c) |
| 66 | // X64: define x86_vectorcallcc void @"\01hva2@@144"(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, %struct.HVA4* align 16 %b, <4 x float> %c) |
| 67 | |
| 68 | void __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {} |
| 69 | // CHECK: define x86_vectorcallcc void @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* inreg %f) |
| 70 | // X64: define x86_vectorcallcc void @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* align 16 %f) |
| 71 | |
| 72 | typedef float __attribute__((ext_vector_type(3))) v3f32; |
| 73 | struct OddSizeHVA { v3f32 x, y; }; |
| 74 | |
| 75 | void __vectorcall odd_size_hva(struct OddSizeHVA a) {} |
| 76 | // CHECK: define x86_vectorcallcc void @"\01odd_size_hva@@32"(<3 x float> %a.0, <3 x float> %a.1) |
| 77 | // X64: define x86_vectorcallcc void @"\01odd_size_hva@@32"(<3 x float> %a.0, <3 x float> %a.1) |