1 // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -ffreestanding -triple=i386-pc-win32       | FileCheck %s --check-prefix=X32
2 // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -ffreestanding -triple=x86_64-pc-win32     | FileCheck %s --check-prefix=X64
3 
v1(int a,int b)4 void __vectorcall v1(int a, int b) {}
5 // X32: define dso_local x86_vectorcallcc void @"\01v1@@8"(i32 inreg noundef %a, i32 inreg noundef %b)
6 // X64: define dso_local x86_vectorcallcc void @"\01v1@@16"(i32 noundef %a, i32 noundef %b)
7 
v2(char a,char b)8 void __vectorcall v2(char a, char b) {}
9 // X32: define dso_local x86_vectorcallcc void @"\01v2@@8"(i8 inreg noundef signext %a, i8 inreg noundef signext %b)
10 // X64: define dso_local x86_vectorcallcc void @"\01v2@@16"(i8 noundef %a, i8 noundef %b)
11 
12 struct Small { int x; };
v3(int a,struct Small b,int c)13 void __vectorcall v3(int a, struct Small b, int c) {}
14 // X32: define dso_local x86_vectorcallcc void @"\01v3@@12"(i32 inreg noundef %a, i32 %b.0, i32 inreg noundef %c)
15 // X64: define dso_local x86_vectorcallcc void @"\01v3@@24"(i32 noundef %a, i32 %b.coerce, i32 noundef %c)
16 
17 struct Large { int a[5]; };
v4(int a,struct Large b,int c)18 void __vectorcall v4(int a, struct Large b, int c) {}
19 // X32: define dso_local x86_vectorcallcc void @"\01v4@@28"(i32 inreg noundef %a, %struct.Large* noundef byval(%struct.Large) align 4 %b, i32 inreg noundef %c)
20 // X64: define dso_local x86_vectorcallcc void @"\01v4@@40"(i32 noundef %a, %struct.Large* noundef %b, i32 noundef %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 
hfa1(int a,struct HFA4 b,int c)26 void __vectorcall hfa1(int a, struct HFA4 b, int c) {}
27 // X32: define dso_local x86_vectorcallcc void @"\01hfa1@@40"(i32 inreg noundef %a, %struct.HFA4 inreg %b.coerce, i32 inreg noundef %c)
28 // X64: define dso_local x86_vectorcallcc void @"\01hfa1@@48"(i32 noundef %a, %struct.HFA4 inreg %b.coerce, i32 noundef %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.
hfa2(struct HFA4 a,struct HFA4 b,double c)33 void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {}
34 // X32: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* inreg noundef %b, double inreg noundef %c)
35 // X64: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* noundef %b, double noundef %c)
36 
37 // Ensure that we pass builtin types directly while counting them against the
38 // SSE register usage.
hfa3(double a,double b,double c,double d,double e,struct HFA2 f)39 void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {}
40 // X32: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double inreg noundef %a, double inreg noundef %b, double inreg noundef %c, double inreg noundef %d, double inreg noundef %e, %struct.HFA2* inreg noundef %f)
41 // X64: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, %struct.HFA2* noundef %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.
hfa4(struct HFA5 a)46 void __vectorcall hfa4(struct HFA5 a) {}
47 // X32: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* noundef byval(%struct.HFA5) align 4 %0)
48 // X64: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* noundef %a)
49 
50 // Return HFAs of 4 or fewer elements in registers.
51 static struct HFA2 g_hfa2;
hfa5(void)52 struct HFA2 __vectorcall hfa5(void) { return g_hfa2; }
53 // X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
54 // X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
55 
56 typedef float __attribute__((vector_size(16))) v4f32;
57 struct HVA2 { v4f32 x, y; };
58 struct HVA3 { v4f32 w, x, y; };
59 struct HVA4 { v4f32 w, x, y, z; };
60 struct HVA5 { v4f32 w, x, y, z, p; };
61 
hva1(int a,struct HVA4 b,int c)62 v4f32 __vectorcall hva1(int a, struct HVA4 b, int c) {return b.w;}
63 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@72"(i32 inreg noundef %a, %struct.HVA4 inreg %b.coerce, i32 inreg noundef %c)
64 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@80"(i32 noundef %a, %struct.HVA4 inreg %b.coerce, i32 noundef %c)
65 
hva2(struct HVA4 a,struct HVA4 b,v4f32 c)66 v4f32 __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {return c;}
67 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg noundef %b, <4 x float> inreg noundef %c)
68 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* noundef %b, <4 x float> noundef %c)
69 
hva3(v4f32 a,v4f32 b,v4f32 c,v4f32 d,v4f32 e,struct HVA2 f)70 v4f32 __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {return f.x;}
71 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> inreg noundef %a, <4 x float> inreg noundef %b, <4 x float> inreg noundef %c, <4 x float> inreg noundef %d, <4 x float> inreg noundef %e, %struct.HVA2* inreg noundef %f)
72 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c, <4 x float> noundef %d, <4 x float> noundef %e, %struct.HVA2* noundef %f)
73 
74 // vector types have higher priority then HVA structures, So vector types are allocated first
75 // and HVAs are allocated if enough registers are available
hva4(struct HVA4 a,struct HVA2 b,v4f32 c)76 v4f32 __vectorcall hva4(struct HVA4 a, struct HVA2 b, v4f32 c) {return b.y;}
77 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* inreg noundef %b, <4 x float> inreg noundef %c)
78 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* noundef %b, <4 x float> noundef %c)
79 
hva5(struct HVA3 a,struct HVA3 b,v4f32 c,struct HVA2 d)80 v4f32 __vectorcall hva5(struct HVA3 a, struct HVA3 b, v4f32 c, struct HVA2 d) {return d.y;}
81 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* inreg noundef %b, <4 x float> inreg noundef %c, %struct.HVA2 inreg %d.coerce)
82 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* noundef %b, <4 x float> noundef %c, %struct.HVA2 inreg %d.coerce)
83 
hva6(struct HVA4 a,struct HVA4 b)84 struct HVA4 __vectorcall hva6(struct HVA4 a, struct HVA4 b) { return b;}
85 // X32: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg noundef %b)
86 // X64: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* noundef %b)
87 
hva7(void)88 struct HVA5 __vectorcall hva7(void) {struct HVA5 a = {}; return a;}
89 // X32: define dso_local x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* inreg noalias sret(%struct.HVA5) align 16 %agg.result)
90 // X64: define dso_local x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* noalias sret(%struct.HVA5) align 16 %agg.result)
91 
hva8(v4f32 a,v4f32 b,v4f32 c,v4f32 d,int e,v4f32 f)92 v4f32 __vectorcall hva8(v4f32 a, v4f32 b, v4f32 c, v4f32 d, int e, v4f32 f) {return f;}
93 // X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> inreg noundef %a, <4 x float> inreg noundef %b, <4 x float> inreg noundef %c, <4 x float> inreg noundef %d, i32 inreg noundef %e, <4 x float> inreg noundef %f)
94 // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@88"(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c, <4 x float> noundef %d, i32 noundef %e, <4 x float> noundef %f)
95 
96 typedef float __attribute__((ext_vector_type(3))) v3f32;
97 struct OddSizeHVA { v3f32 x, y; };
98 
odd_size_hva(struct OddSizeHVA a)99 void __vectorcall odd_size_hva(struct OddSizeHVA a) {}
100 // X32: define dso_local x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
101 // X64: define dso_local x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
102 
103 // The Vectorcall ABI only allows passing the first 6 items in registers in x64, so this shouldn't
104 // consider 'p7' as a register.  Instead p5 gets put into the register on the second pass.
105 // x86 should pass p2, p6 and p7 in registers, then p1 in the second pass.
AddParticles(struct HFA2 p1,float p2,struct HFA4 p3,int p4,struct HFA2 p5,float p6,float p7,int p8)106 struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, int p4, struct HFA2 p5, float p6, float p7, int p8){ return p1;}
107 // X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float inreg noundef %p2, %struct.HFA4* inreg noundef %p3, i32 inreg noundef %p4, %struct.HFA2* noundef %p5, float inreg noundef %p6, float inreg noundef %p7, i32 noundef %p8)
108 // X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float noundef %p2, %struct.HFA4* noundef %p3, i32 noundef %p4, %struct.HFA2 inreg %p5.coerce, float noundef %p6, float noundef %p7, i32 noundef %p8)
109 
110 // Vectorcall in both architectures allows passing of an HVA as long as there is room,
111 // even if it is not one of the first 6 arguments.  First pass puts p4 into a
112 // register on both.  p9 ends up in a register in x86 only.  Second pass puts p1
113 // in a register, does NOT put p7 in a register (since theres no room), then puts
114 // p8 in a register.
HVAAnywhere(struct HFA2 p1,int p2,int p3,float p4,int p5,int p6,struct HFA4 p7,struct HFA2 p8,float p9)115 void __vectorcall HVAAnywhere(struct HFA2 p1, int p2, int p3, float p4, int p5, int p6, struct HFA4 p7, struct HFA2 p8, float p9){}
116 // X32: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg noundef %p2, i32 inreg noundef %p3, float inreg noundef %p4, i32 noundef %p5, i32 noundef %p6, %struct.HFA4* noundef %p7, %struct.HFA2 inreg %p8.coerce, float inreg noundef %p9)
117 // X64: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 noundef %p2, i32 noundef %p3, float noundef %p4, i32 noundef %p5, i32 noundef %p6, %struct.HFA4* noundef %p7, %struct.HFA2 inreg %p8.coerce, float noundef %p9)
118 
119 #ifndef __x86_64__
120 // This covers the three ways XMM values can be passed on 32-bit x86:
121 // - directly in XMM register (xmm5)
122 // - indirectly by address, address in GPR (ecx)
123 // - indirectly by address, address on stack
vectorcall_indirect_vec(double xmm0,double xmm1,double xmm2,double xmm3,double xmm4,v4f32 xmm5,v4f32 ecx,int edx,v4f32 mem)124 void __vectorcall vectorcall_indirect_vec(
125     double xmm0, double xmm1, double xmm2, double xmm3, double xmm4,
126     v4f32 xmm5, v4f32 ecx, int edx, v4f32 mem) {
127 }
128 
129 // X32: define dso_local x86_vectorcallcc void @"\01vectorcall_indirect_vec@@{{[0-9]+}}"
130 // X32-SAME: (double inreg noundef %xmm0,
131 // X32-SAME: double inreg noundef %xmm1,
132 // X32-SAME: double inreg noundef %xmm2,
133 // X32-SAME: double inreg noundef %xmm3,
134 // X32-SAME: double inreg noundef %xmm4,
135 // X32-SAME: <4 x float> inreg noundef %xmm5,
136 // X32-SAME: <4 x float>* inreg noundef %0,
137 // X32-SAME: i32 inreg noundef %edx,
138 // X32-SAME: <4 x float>* noundef %1)
139 #endif
140