1 // RUN: %clang_cc1 -w -triple i686-pc-win32 -emit-llvm -o - %s | FileCheck %s
4 // MSVC passes up to three vectors in registers, and the rest indirectly. Check
5 // that both are compatible with an inalloca prototype.
9 NonTrivial(const NonTrivial
&o
);
13 typedef float __m128
__attribute__((__vector_size__(16), __aligned__(16)));
16 // nt, w, and q will be in the inalloca pack.
17 void receive_vec_128(NonTrivial nt
, __m128 x
, __m128 y
, __m128 z
, __m128 w
, __m128 q
) {
18 gv128
= x
+ y
+ z
+ w
+ q
;
20 // CHECK-LABEL: define dso_local void @"?receive_vec_128@@YAXUNonTrivial@@T__m128@@1111@Z"
21 // CHECK-SAME: (<4 x float> inreg noundef %x,
22 // CHECK-SAME: <4 x float> inreg noundef %y,
23 // CHECK-SAME: <4 x float> inreg noundef %z,
24 // CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca(<{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>) %0)
28 receive_vec_128(NonTrivial(), z
, z
, z
, z
, z
);
30 // CHECK-LABEL: define dso_local void @"?pass_vec_128@@YAXXZ"()
31 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 0
32 // CHECK: call x86_thiscallcc noundef %struct.NonTrivial* @"??0NonTrivial@@QAE@XZ"(%struct.NonTrivial* {{[^,]*}} %{{.*}})
34 // Store q, store temp alloca.
35 // CHECK: store <4 x float> %{{[^,]*}}, <4 x float>* %{{[^,]*}}, align 16
36 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 1
37 // CHECK: store <4 x float>* %{{[^,]*}}, <4 x float>** %{{[^,]*}}, align 4
39 // Store w, store temp alloca.
40 // CHECK: store <4 x float> %{{[^,]*}}, <4 x float>* %{{[^,]*}}, align 16
41 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 2
42 // CHECK: store <4 x float>* %{{[^,]*}}, <4 x float>** %{{[^,]*}}, align 4
44 // CHECK: call void @"?receive_vec_128@@YAXUNonTrivial@@T__m128@@1111@Z"
45 // CHECK-SAME: (<4 x float> inreg noundef %{{[^,]*}},
46 // CHECK-SAME: <4 x float> inreg noundef %{{[^,]*}},
47 // CHECK-SAME: <4 x float> inreg noundef %{{[^,]*}},
48 // CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca(<{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>) %{{[^,]*}})
50 // w will be passed indirectly by register, and q will be passed indirectly, but
51 // the pointer will be in memory.
52 void __fastcall
fastcall_receive_vec(__m128 x
, __m128 y
, __m128 z
, __m128 w
, int edx
, __m128 q
, NonTrivial nt
) {
53 gv128
= x
+ y
+ z
+ w
+ q
;
55 // CHECK-LABEL: define dso_local x86_fastcallcc void @"?fastcall_receive_vec@@Y{{[^"]*}}"
56 // CHECK-SAME: (<4 x float> inreg noundef %x,
57 // CHECK-SAME: <4 x float> inreg noundef %y,
58 // CHECK-SAME: <4 x float> inreg noundef %z,
59 // CHECK-SAME: <4 x float>* inreg noundef %0,
60 // CHECK-SAME: i32 inreg noundef %edx,
61 // CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca(<{ <4 x float>*, %struct.NonTrivial }>) %1)
64 void __vectorcall
vectorcall_receive_vec(double xmm0
, double xmm1
, double xmm2
,
65 __m128 x
, __m128 y
, __m128 z
,
66 __m128 w
, int edx
, __m128 q
, NonTrivial nt
) {
67 gv128
= x
+ y
+ z
+ w
+ q
;
69 // CHECK-LABEL: define dso_local x86_vectorcallcc void @"?vectorcall_receive_vec@@Y{{[^"]*}}"
70 // CHECK-SAME: (double inreg noundef %xmm0,
71 // CHECK-SAME: double inreg noundef %xmm1,
72 // CHECK-SAME: double inreg noundef %xmm2,
73 // CHECK-SAME: <4 x float> inreg noundef %x,
74 // CHECK-SAME: <4 x float> inreg noundef %y,
75 // CHECK-SAME: <4 x float> inreg noundef %z,
76 // CHECK-SAME: <4 x float>* inreg noundef %0,
77 // CHECK-SAME: i32 inreg noundef %edx,
78 // CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca(<{ <4 x float>*, %struct.NonTrivial }>) %1)