79 lines · cpp
1// RUN: %clang_cc1 -w -triple i686-pc-win32 -emit-llvm -o - %s | FileCheck %s2 3// PR443954// MSVC passes up to three vectors in registers, and the rest indirectly. Check5// that both are compatible with an inalloca prototype.6 7struct NonTrivial {8 NonTrivial();9 NonTrivial(const NonTrivial &o);10 unsigned handle;11};12 13typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));14__m128 gv128;15 16// nt, w, and q will be in the inalloca pack.17void 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 26void 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 032// 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 1636// CHECK: getelementptr inbounds nuw <{ %struct.NonTrivial, ptr, ptr }>, ptr %{{[^,]*}}, i32 0, i32 137// CHECK: store ptr %{{[^,]*}}, ptr %{{[^,]*}}, align 438 39// Store w, store temp alloca.40// CHECK: store <4 x float> %{{[^,]*}}, ptr %{{[^,]*}}, align 1641// CHECK: getelementptr inbounds nuw <{ %struct.NonTrivial, ptr, ptr }>, ptr %{{[^,]*}}, i32 0, i32 242// CHECK: store ptr %{{[^,]*}}, ptr %{{[^,]*}}, align 443 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, but51// the pointer will be in memory.52void __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 dead_on_return inreg noundef %0,60// CHECK-SAME: i32 inreg noundef %edx,61// CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1)62 63 64void __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 dead_on_return inreg noundef %0,77// CHECK-SAME: i32 inreg noundef %edx,78// CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1)79