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