xref: /llvm-project/clang/test/CodeGenCXX/inalloca-vector.cpp (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1 // RUN: %clang_cc1 -w -triple i686-pc-win32 -emit-llvm -o - %s | FileCheck %s
2 
3 // PR44395
4 // MSVC passes up to three vectors in registers, and the rest indirectly. Check
5 // that both are compatible with an inalloca prototype.
6 
7 struct NonTrivial {
8   NonTrivial();
9   NonTrivial(const NonTrivial &o);
10   unsigned handle;
11 };
12 
13 typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
14 __m128 gv128;
15 
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;
19 }
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: ptr inalloca(<{ %struct.NonTrivial, ptr, ptr }>) %0)
25 
26 void pass_vec_128() {
27   __m128 z = {0};
28   receive_vec_128(NonTrivial(), z, z, z, z, z);
29 }
30 // CHECK-LABEL: define dso_local void @"?pass_vec_128@@YAXXZ"()
31 // CHECK: getelementptr inbounds nuw <{ %struct.NonTrivial, ptr, ptr }>, ptr %{{[^,]*}}, i32 0, i32 0
32 // CHECK: call x86_thiscallcc noundef ptr @"??0NonTrivial@@QAE@XZ"(ptr {{[^,]*}} %{{.*}})
33 
34 // Store q, store temp alloca.
35 // CHECK: store <4 x float> %{{[^,]*}}, ptr %{{[^,]*}}, align 16
36 // CHECK: getelementptr inbounds nuw <{ %struct.NonTrivial, ptr, ptr }>, ptr %{{[^,]*}}, i32 0, i32 1
37 // CHECK: store ptr %{{[^,]*}}, ptr %{{[^,]*}}, align 4
38 
39 // Store w, store temp alloca.
40 // CHECK: store <4 x float> %{{[^,]*}}, ptr %{{[^,]*}}, align 16
41 // CHECK: getelementptr inbounds nuw <{ %struct.NonTrivial, ptr, ptr }>, ptr %{{[^,]*}}, i32 0, i32 2
42 // CHECK: store ptr %{{[^,]*}}, ptr %{{[^,]*}}, align 4
43 
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: ptr inalloca(<{ %struct.NonTrivial, ptr, ptr }>) %{{[^,]*}})
49 
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;
54 }
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: ptr inreg noundef %0,
60 // CHECK-SAME: i32 inreg noundef %edx,
61 // CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1)
62 
63 
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;
68 }
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: ptr inreg noundef %0,
77 // CHECK-SAME: i32 inreg noundef %edx,
78 // CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1)
79