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