79 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -w -triple i686-pc-win32 -emit-llvm -o - %s | FileCheck %s
 | 
						|
 | 
						|
// PR44395
 | 
						|
// MSVC passes up to three vectors in registers, and the rest indirectly. Check
 | 
						|
// that both are compatible with an inalloca prototype.
 | 
						|
 | 
						|
struct NonTrivial {
 | 
						|
  NonTrivial();
 | 
						|
  NonTrivial(const NonTrivial &o);
 | 
						|
  unsigned handle;
 | 
						|
};
 | 
						|
 | 
						|
typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
 | 
						|
__m128 gv128;
 | 
						|
 | 
						|
// nt, w, and q will be in the inalloca pack.
 | 
						|
void receive_vec_128(NonTrivial nt, __m128 x, __m128 y, __m128 z, __m128 w, __m128 q) {
 | 
						|
  gv128 = x + y + z + w + q;
 | 
						|
}
 | 
						|
// CHECK-LABEL: define dso_local void  @"?receive_vec_128@@YAXUNonTrivial@@T__m128@@1111@Z"
 | 
						|
// CHECK-SAME: (<4 x float> inreg %x,
 | 
						|
// CHECK-SAME: <4 x float> inreg %y,
 | 
						|
// CHECK-SAME: <4 x float> inreg %z,
 | 
						|
// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca %0)
 | 
						|
 | 
						|
void pass_vec_128() {
 | 
						|
  __m128 z = {0};
 | 
						|
  receive_vec_128(NonTrivial(), z, z, z, z, z);
 | 
						|
}
 | 
						|
// CHECK-LABEL: define dso_local void @"?pass_vec_128@@YAXXZ"()
 | 
						|
// CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 0
 | 
						|
// CHECK: call x86_thiscallcc %struct.NonTrivial* @"??0NonTrivial@@QAE@XZ"(%struct.NonTrivial* %{{.*}})
 | 
						|
 | 
						|
// Store q, store temp alloca.
 | 
						|
// CHECK: store <4 x float> %{{[^,]*}}, <4 x float>* %{{[^,]*}}, align 16
 | 
						|
// CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 1
 | 
						|
// CHECK: store <4 x float>* %{{[^,]*}}, <4 x float>** %{{[^,]*}}, align 4
 | 
						|
 | 
						|
// Store w, store temp alloca.
 | 
						|
// CHECK: store <4 x float> %{{[^,]*}}, <4 x float>* %{{[^,]*}}, align 16
 | 
						|
// CHECK: getelementptr inbounds <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>, <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* %{{[^,]*}}, i32 0, i32 2
 | 
						|
// CHECK: store <4 x float>* %{{[^,]*}}, <4 x float>** %{{[^,]*}}, align 4
 | 
						|
 | 
						|
// CHECK: call void @"?receive_vec_128@@YAXUNonTrivial@@T__m128@@1111@Z"
 | 
						|
// CHECK-SAME: (<4 x float> inreg %{{[^,]*}},
 | 
						|
// CHECK-SAME: <4 x float> inreg %{{[^,]*}},
 | 
						|
// CHECK-SAME: <4 x float> inreg %{{[^,]*}},
 | 
						|
// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca %{{[^,]*}})
 | 
						|
 | 
						|
// w will be passed indirectly by register, and q will be passed indirectly, but
 | 
						|
// the pointer will be in memory.
 | 
						|
void __fastcall fastcall_receive_vec(__m128 x, __m128 y, __m128 z, __m128 w, int edx, __m128 q, NonTrivial nt) {
 | 
						|
  gv128 = x + y + z + w + q;
 | 
						|
}
 | 
						|
// CHECK-LABEL: define dso_local x86_fastcallcc void @"?fastcall_receive_vec@@Y{{[^"]*}}"
 | 
						|
// CHECK-SAME: (<4 x float> inreg %x,
 | 
						|
// CHECK-SAME: <4 x float> inreg %y,
 | 
						|
// CHECK-SAME: <4 x float> inreg %z,
 | 
						|
// CHECK-SAME: <4 x float>* inreg %0,
 | 
						|
// CHECK-SAME: i32 inreg %edx,
 | 
						|
// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1)
 | 
						|
 | 
						|
 | 
						|
void __vectorcall vectorcall_receive_vec(double xmm0, double xmm1, double xmm2,
 | 
						|
                                         __m128 x, __m128 y, __m128 z,
 | 
						|
                                         __m128 w, int edx, __m128 q, NonTrivial nt) {
 | 
						|
  gv128 = x + y + z + w + q;
 | 
						|
}
 | 
						|
// CHECK-LABEL: define dso_local x86_vectorcallcc void @"?vectorcall_receive_vec@@Y{{[^"]*}}"
 | 
						|
// CHECK-SAME: (double inreg %xmm0,
 | 
						|
// CHECK-SAME: double inreg %xmm1,
 | 
						|
// CHECK-SAME: double inreg %xmm2,
 | 
						|
// CHECK-SAME: <4 x float> inreg %x,
 | 
						|
// CHECK-SAME: <4 x float> inreg %y,
 | 
						|
// CHECK-SAME: <4 x float> inreg %z,
 | 
						|
// CHECK-SAME: <4 x float>* inreg %0,
 | 
						|
// CHECK-SAME: i32 inreg %edx,
 | 
						|
// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1)
 |