1; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -enable-ipra=0 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI %s
2; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -enable-ipra=0 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,CI %s
3
4%struct.ByValStruct = type { [4 x i32] }
5
6; GCN-LABEL: {{^}}void_func_byval_struct:
7; GCN: s_mov_b32 s5, s32
8; GCN: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s5 offset:4{{$}}
9; GCN-NOT: s32
10; GCN: buffer_store_dword [[LOAD0]], off, s[0:3], s5 offset:4{{$}}
11; GCN-NOT: s32
12
13; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s5 offset:20{{$}}
14; GCN-NOT: s32
15; GCN: buffer_store_dword [[LOAD1]], off, s[0:3], s5 offset:20{{$}}
16; GCN-NOT: s32
17define void @void_func_byval_struct(%struct.ByValStruct addrspace(5)* byval noalias nocapture align 4 %arg0, %struct.ByValStruct addrspace(5)* byval noalias nocapture align 4 %arg1) #1 {
18entry:
19  %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg0, i32 0, i32 0, i32 0
20  %tmp = load volatile i32, i32 addrspace(5)* %arrayidx, align 4
21  %add = add nsw i32 %tmp, 1
22  store volatile i32 %add, i32 addrspace(5)* %arrayidx, align 4
23  %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg1, i32 0, i32 0, i32 0
24  %tmp1 = load volatile i32, i32 addrspace(5)* %arrayidx2, align 4
25  %add3 = add nsw i32 %tmp1, 2
26  store volatile i32 %add3, i32 addrspace(5)* %arrayidx2, align 4
27  store volatile i32 9, i32 addrspace(1)* null, align 4
28  ret void
29}
30
31; GCN-LABEL: {{^}}void_func_byval_struct_non_leaf:
32; GCN: s_mov_b32 s5, s32
33; GCN-DAG: buffer_store_dword v32
34; GCN-DAG: buffer_store_dword v33
35; GCN-NOT: v_writelane_b32 v{{[0-9]+}}, s32
36; GCN: v_writelane_b32
37
38; GCN-DAG: s_add_u32 s32, s32, 0xb00{{$}}
39
40; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s5 offset:4{{$}}
41; GCN: v_add_{{[iu]}}32_e32 [[ADD0:v[0-9]+]], vcc, 1, [[LOAD0]]
42; GCN: buffer_store_dword [[ADD0]], off, s[0:3], s5 offset:4{{$}}
43
44; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s5 offset:20{{$}}
45; GCN: v_add_{{[iu]}}32_e32 [[ADD1:v[0-9]+]], vcc, 2, [[LOAD1]]
46
47; GCN: s_swappc_b64
48
49; GCN: buffer_store_dword [[ADD1]], off, s[0:3], s5 offset:20{{$}}
50
51; GCN: v_readlane_b32
52; GCN-NOT: v_readlane_b32 s32
53; GCN: buffer_load_dword v32,
54; GCN: buffer_load_dword v33,
55; GCN: s_sub_u32 s32, s32, 0xb00{{$}}
56; GCN: s_setpc_b64
57define void  @void_func_byval_struct_non_leaf(%struct.ByValStruct addrspace(5)* byval noalias nocapture align 4 %arg0, %struct.ByValStruct addrspace(5)* byval noalias nocapture align 4 %arg1) #1 {
58entry:
59  %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg0, i32 0, i32 0, i32 0
60  %tmp = load volatile i32, i32 addrspace(5)* %arrayidx, align 4
61  %add = add nsw i32 %tmp, 1
62  store volatile i32 %add, i32 addrspace(5)* %arrayidx, align 4
63  %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg1, i32 0, i32 0, i32 0
64  %tmp1 = load volatile i32, i32 addrspace(5)* %arrayidx2, align 4
65  %add3 = add nsw i32 %tmp1, 2
66  call void @external_void_func_void()
67  store volatile i32 %add3, i32 addrspace(5)* %arrayidx2, align 4
68  store volatile i32 9, i32 addrspace(1)* null, align 4
69  ret void
70}
71
72; GCN-LABEL: {{^}}call_void_func_byval_struct_func:
73; GCN: s_mov_b32 s5, s32
74; GCN-DAG: s_add_u32 s32, s32, 0xc00{{$}}
75; GCN-DAG: v_writelane_b32
76
77; GCN-DAG: v_mov_b32_e32 [[NINE:v[0-9]+]], 9
78; GCN-DAG: v_mov_b32_e32 [[THIRTEEN:v[0-9]+]], 13
79
80; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s5 offset:8
81; GCN-DAG: buffer_store_dword [[THIRTEEN]], off, s[0:3], s5 offset:24
82
83; GCN: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s5 offset:8
84; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s5 offset:12
85; GCN: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3], s5 offset:16
86; GCN: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3], s5 offset:20
87
88; GCN-NOT: s_add_u32 s32, s32, 0x800
89
90; GCN-DAG: buffer_store_dword [[LOAD0]], off, s[0:3], s32 offset:4{{$}}
91; GCN-DAG: buffer_store_dword [[LOAD1]], off, s[0:3], s32 offset:8
92; GCN-DAG: buffer_store_dword [[LOAD2]], off, s[0:3], s32 offset:12
93; GCN-DAG: buffer_store_dword [[LOAD3]], off, s[0:3], s32 offset:16
94
95; GCN: buffer_load_dword [[LOAD4:v[0-9]+]], off, s[0:3], s5 offset:24
96; GCN: buffer_load_dword [[LOAD5:v[0-9]+]], off, s[0:3], s5 offset:28
97; GCN: buffer_load_dword [[LOAD6:v[0-9]+]], off, s[0:3], s5 offset:32
98; GCN: buffer_load_dword [[LOAD7:v[0-9]+]], off, s[0:3], s5 offset:36
99
100; GCN-DAG: buffer_store_dword [[LOAD4]], off, s[0:3], s32 offset:20
101; GCN-DAG: buffer_store_dword [[LOAD5]], off, s[0:3], s32 offset:24
102; GCN-DAG: buffer_store_dword [[LOAD6]], off, s[0:3], s32 offset:28
103; GCN-DAG: buffer_store_dword [[LOAD7]], off, s[0:3], s32 offset:32
104
105; GCN: s_swappc_b64
106; GCN-NOT: v_readlane_b32 s32
107; GCN: v_readlane_b32
108; GCN-NOT: v_readlane_b32 s32
109
110; GCN-NOT: s_sub_u32 s32, s32, 0x800
111
112; GCN: s_sub_u32 s32, s32, 0xc00{{$}}
113; GCN-NEXT: s_waitcnt
114; GCN-NEXT: s_setpc_b64
115define void @call_void_func_byval_struct_func() #0 {
116entry:
117  %arg0 = alloca %struct.ByValStruct, align 4, addrspace(5)
118  %arg1 = alloca %struct.ByValStruct, align 4, addrspace(5)
119  %tmp = bitcast %struct.ByValStruct addrspace(5)* %arg0 to i8 addrspace(5)*
120  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp)
121  %tmp1 = bitcast %struct.ByValStruct addrspace(5)* %arg1 to i8 addrspace(5)*
122  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp1)
123  %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg0, i32 0, i32 0, i32 0
124  store volatile i32 9, i32 addrspace(5)* %arrayidx, align 4
125  %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg1, i32 0, i32 0, i32 0
126  store volatile i32 13, i32 addrspace(5)* %arrayidx2, align 4
127  call void @void_func_byval_struct(%struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg0, %struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg1)
128  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp1)
129  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp)
130  ret void
131}
132
133; GCN-LABEL: {{^}}call_void_func_byval_struct_kernel:
134; GCN: s_mov_b32 s33, s7
135; GCN: s_add_u32 s32, s33, 0xa00{{$}}
136
137; GCN-DAG: v_mov_b32_e32 [[NINE:v[0-9]+]], 9
138; GCN-DAG: v_mov_b32_e32 [[THIRTEEN:v[0-9]+]], 13
139; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s33 offset:8
140; GCN: buffer_store_dword [[THIRTEEN]], off, s[0:3], s33 offset:24
141
142; GCN-NOT: s_add_u32 s32, s32, 0x800
143
144; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s33 offset:8
145; GCN-DAG: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s33 offset:12
146; GCN-DAG: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3], s33 offset:16
147; GCN-DAG: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3], s33 offset:20
148
149; GCN-DAG: buffer_store_dword [[LOAD0]], off, s[0:3], s32 offset:4{{$}}
150; GCN-DAG: buffer_store_dword [[LOAD1]], off, s[0:3], s32 offset:8
151; GCN-DAG: buffer_store_dword [[LOAD2]], off, s[0:3], s32 offset:12
152; GCN-DAG: buffer_store_dword [[LOAD3]], off, s[0:3], s32 offset:16
153
154; GCN-DAG: buffer_load_dword [[LOAD4:v[0-9]+]], off, s[0:3], s33 offset:24
155; GCN-DAG: buffer_load_dword [[LOAD5:v[0-9]+]], off, s[0:3], s33 offset:28
156; GCN-DAG: buffer_load_dword [[LOAD6:v[0-9]+]], off, s[0:3], s33 offset:32
157; GCN-DAG: buffer_load_dword [[LOAD7:v[0-9]+]], off, s[0:3], s33 offset:36
158
159; GCN-DAG: buffer_store_dword [[LOAD4]], off, s[0:3], s32 offset:20
160; GCN-DAG: buffer_store_dword [[LOAD5]], off, s[0:3], s32 offset:24
161; GCN-DAG: buffer_store_dword [[LOAD6]], off, s[0:3], s32 offset:28
162; GCN-DAG: buffer_store_dword [[LOAD7]], off, s[0:3], s32 offset:32
163
164
165; GCN: s_swappc_b64
166; GCN-NOT: s_sub_u32 s32
167; GCN: s_endpgm
168define amdgpu_kernel void @call_void_func_byval_struct_kernel() #0 {
169entry:
170  %arg0 = alloca %struct.ByValStruct, align 4, addrspace(5)
171  %arg1 = alloca %struct.ByValStruct, align 4, addrspace(5)
172  %tmp = bitcast %struct.ByValStruct addrspace(5)* %arg0 to i8 addrspace(5)*
173  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp)
174  %tmp1 = bitcast %struct.ByValStruct addrspace(5)* %arg1 to i8 addrspace(5)*
175  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp1)
176  %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg0, i32 0, i32 0, i32 0
177  store volatile i32 9, i32 addrspace(5)* %arrayidx, align 4
178  %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg1, i32 0, i32 0, i32 0
179  store volatile i32 13, i32 addrspace(5)* %arrayidx2, align 4
180  call void @void_func_byval_struct(%struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg0, %struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg1)
181  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp1)
182  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp)
183  ret void
184}
185
186; GCN-LABEL: {{^}}call_void_func_byval_struct_kernel_no_frame_pointer_elim:
187define amdgpu_kernel void @call_void_func_byval_struct_kernel_no_frame_pointer_elim() #2 {
188entry:
189  %arg0 = alloca %struct.ByValStruct, align 4, addrspace(5)
190  %arg1 = alloca %struct.ByValStruct, align 4, addrspace(5)
191  %tmp = bitcast %struct.ByValStruct addrspace(5)* %arg0 to i8 addrspace(5)*
192  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp)
193  %tmp1 = bitcast %struct.ByValStruct addrspace(5)* %arg1 to i8 addrspace(5)*
194  call void @llvm.lifetime.start.p5i8(i64 32, i8 addrspace(5)* %tmp1)
195  %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg0, i32 0, i32 0, i32 0
196  store volatile i32 9, i32 addrspace(5)* %arrayidx, align 4
197  %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct addrspace(5)* %arg1, i32 0, i32 0, i32 0
198  store volatile i32 13, i32 addrspace(5)* %arrayidx2, align 4
199  call void @void_func_byval_struct(%struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg0, %struct.ByValStruct addrspace(5)* byval nonnull align 4 %arg1)
200  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp1)
201  call void @llvm.lifetime.end.p5i8(i64 32, i8 addrspace(5)* %tmp)
202  ret void
203}
204
205declare void @external_void_func_void() #0
206
207declare void @llvm.lifetime.start.p5i8(i64, i8 addrspace(5)* nocapture) #3
208declare void @llvm.lifetime.end.p5i8(i64, i8 addrspace(5)* nocapture) #3
209
210attributes #0 = { nounwind }
211attributes #1 = { noinline norecurse nounwind }
212attributes #2 = { nounwind norecurse "no-frame-pointer-elim"="true" }
213