1// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -enable-var-scope -check-prefixes=COM,X86 %s 2// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn-amdhsa-amd-amdgizcl | FileCheck -enable-var-scope -check-prefixes=COM,AMD %s 3 4typedef struct { 5 int cells[9]; 6} Mat3X3; 7 8typedef struct { 9 int cells[16]; 10} Mat4X4; 11 12typedef struct { 13 int cells[1024]; 14} Mat32X32; 15 16typedef struct { 17 int cells[4096]; 18} Mat64X64; 19 20struct StructOneMember { 21 int2 x; 22}; 23 24struct StructTwoMember { 25 int2 x; 26 int2 y; 27}; 28 29struct LargeStructOneMember { 30 int2 x[100]; 31}; 32 33struct LargeStructTwoMember { 34 int2 x[40]; 35 int2 y[20]; 36}; 37 38 39// X86-LABEL: define void @foo(%struct.Mat4X4* noalias sret %agg.result, %struct.Mat3X3* byval align 4 %in) 40// AMD-LABEL: define %struct.Mat4X4 @foo([9 x i32] %in.coerce) 41Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { 42 Mat4X4 out; 43 return out; 44} 45 46// COM-LABEL: define {{.*}} void @ker 47// Expect two mem copies: one for the argument "in", and one for 48// the return value. 49// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8* 50// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* 51 52// AMD: load [9 x i32], [9 x i32] addrspace(1)* 53// AMD: call %struct.Mat4X4 @foo([9 x i32] 54// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)* 55kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { 56 out[0] = foo(in[1]); 57} 58 59// X86-LABEL: define void @foo_large(%struct.Mat64X64* noalias sret %agg.result, %struct.Mat32X32* byval align 4 %in) 60// AMD-LABEL: define void @foo_large(%struct.Mat64X64 addrspace(5)* noalias sret %agg.result, %struct.Mat32X32 addrspace(5)* byval align 4 %in) 61Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { 62 Mat64X64 out; 63 return out; 64} 65 66// COM-LABEL: define {{.*}} void @ker_large 67// Expect two mem copies: one for the argument "in", and one for 68// the return value. 69// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8* 70// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* 71// AMD: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* 72// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)* 73kernel void ker_large(global Mat32X32 *in, global Mat64X64 *out) { 74 out[0] = foo_large(in[1]); 75} 76 77// AMD-LABEL: define void @FuncOneMember(<2 x i32> %u.coerce) 78void FuncOneMember(struct StructOneMember u) { 79 u.x = (int2)(0, 0); 80} 81 82// AMD-LABEL: define void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %u) 83void FuncOneLargeMember(struct LargeStructOneMember u) { 84 u.x[0] = (int2)(0, 0); 85} 86 87// AMD-LABEL: define amdgpu_kernel void @KernelOneMember 88// AMD-SAME: (<2 x i32> %[[u_coerce:.*]]) 89// AMD: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5) 90// AMD: %[[coerce_dive:.*]] = getelementptr inbounds %struct.StructOneMember, %struct.StructOneMember addrspace(5)* %[[u]], i32 0, i32 0 91// AMD: store <2 x i32> %[[u_coerce]], <2 x i32> addrspace(5)* %[[coerce_dive]] 92// AMD: call void @FuncOneMember(<2 x i32> 93kernel void KernelOneMember(struct StructOneMember u) { 94 FuncOneMember(u); 95} 96 97// AMD-LABEL: define amdgpu_kernel void @KernelLargeOneMember( 98// AMD: %[[U:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5) 99// AMD: store %struct.LargeStructOneMember %u.coerce, %struct.LargeStructOneMember addrspace(5)* %[[U]], align 8 100// AMD: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[U]]) 101kernel void KernelLargeOneMember(struct LargeStructOneMember u) { 102 FuncOneLargeMember(u); 103} 104 105// AMD-LABEL: define void @FuncTwoMember(<2 x i32> %u.coerce0, <2 x i32> %u.coerce1) 106void FuncTwoMember(struct StructTwoMember u) { 107 u.y = (int2)(0, 0); 108} 109 110// AMD-LABEL: define void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %u) 111void FuncLargeTwoMember(struct LargeStructTwoMember u) { 112 u.y[0] = (int2)(0, 0); 113} 114 115 116// AMD-LABEL: define amdgpu_kernel void @KernelTwoMember 117// AMD-SAME: (%struct.StructTwoMember %[[u_coerce:.*]]) 118// AMD: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5) 119// AMD: %[[LD0:.*]] = load <2 x i32>, <2 x i32> addrspace(5)* 120// AMD: %[[LD1:.*]] = load <2 x i32>, <2 x i32> addrspace(5)* 121// AMD: call void @FuncTwoMember(<2 x i32> %[[LD0]], <2 x i32> %[[LD1]]) 122kernel void KernelTwoMember(struct StructTwoMember u) { 123 FuncTwoMember(u); 124} 125 126// AMD-LABEL: define amdgpu_kernel void @KernelLargeTwoMember 127// AMD-SAME: (%struct.LargeStructTwoMember %[[u_coerce:.*]]) 128// AMD: %[[u:.*]] = alloca %struct.LargeStructTwoMember, align 8, addrspace(5) 129// AMD: store %struct.LargeStructTwoMember %[[u_coerce]], %struct.LargeStructTwoMember addrspace(5)* %[[u]] 130// AMD: call void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %[[u]]) 131kernel void KernelLargeTwoMember(struct LargeStructTwoMember u) { 132 FuncLargeTwoMember(u); 133} 134