blob: b53447c8ffbbfe69601831a0437a02f5d014a4e5 [file] [log] [blame]
Matt Arsenaultb62a4eb2017-08-01 19:54:18 +00001; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -amdgpu-function-calls -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI %s
2; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -amdgpu-function-calls -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{{$}}
9; GCN-NOT: s32
10; GCN: buffer_store_dword [[LOAD0]], off, s[0:3], s5{{$}}
11; GCN-NOT: s32
12
13; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s5 offset:16{{$}}
14; GCN-NOT: s32
15; GCN: buffer_store_dword [[LOAD1]], off, s[0:3], s5 offset:16{{$}}
16; GCN-NOT: s32
17define void @void_func_byval_struct(%struct.ByValStruct* byval noalias nocapture align 4 %arg0, %struct.ByValStruct* byval noalias nocapture align 4 %arg1) #1 {
18entry:
19 %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg0, i32 0, i32 0, i32 0
20 %tmp = load volatile i32, i32* %arrayidx, align 4
21 %add = add nsw i32 %tmp, 1
22 store volatile i32 %add, i32* %arrayidx, align 4
23 %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg1, i32 0, i32 0, i32 0
24 %tmp1 = load volatile i32, i32* %arrayidx2, align 4
25 %add3 = add nsw i32 %tmp1, 2
26 store volatile i32 %add3, i32* %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: buffer_store_dword v32
34; GCN: v_writelane_b32
35
36; GCN-DAG: s_add_u32 s32, s32, 0x900{{$}}
37
38; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s5{{$}}
39; GCN: v_add_i32_e32 [[ADD0:v[0-9]+]], vcc, 1, [[LOAD0]]
40; GCN: buffer_store_dword [[ADD0]], off, s[0:3], s5{{$}}
41
42; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s5 offset:16{{$}}
43; GCN: v_add_i32_e32 [[ADD1:v[0-9]+]], vcc, 2, [[LOAD1]]
44
45; GCN: s_swappc_b64
46
47; GCN: buffer_store_dword [[ADD1]], off, s[0:3], s5 offset:16{{$}}
48
49; GCN: v_readlane_b32
50; GCN: buffer_load_dword v32,
51; GCN: s_sub_u32 s32, s32, 0x900{{$}}
52; GCN: s_setpc_b64
53define void @void_func_byval_struct_non_leaf(%struct.ByValStruct* byval noalias nocapture align 4 %arg0, %struct.ByValStruct* byval noalias nocapture align 4 %arg1) #1 {
54entry:
55 %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg0, i32 0, i32 0, i32 0
56 %tmp = load volatile i32, i32* %arrayidx, align 4
57 %add = add nsw i32 %tmp, 1
58 store volatile i32 %add, i32* %arrayidx, align 4
59 %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg1, i32 0, i32 0, i32 0
60 %tmp1 = load volatile i32, i32* %arrayidx2, align 4
61 %add3 = add nsw i32 %tmp1, 2
62 call void @external_void_func_void()
63 store volatile i32 %add3, i32* %arrayidx2, align 4
64 store volatile i32 9, i32 addrspace(1)* null, align 4
65 ret void
66}
67
68; GCN-LABEL: {{^}}call_void_func_byval_struct_func:
69; GCN: s_mov_b32 s5, s32
70; GCN: s_add_u32 s32, s32, 0xa00{{$}}
71; GCN: v_writelane_b32
72
73; GCN-DAG: s_add_u32 s32, s32, 0x800{{$}}
74; GCN-DAG: v_mov_b32_e32 [[NINE:v[0-9]+]], 9
75; GCN-DAG: v_mov_b32_e32 [[THIRTEEN:v[0-9]+]], 13
76
77; VI-DAG: v_lshrrev_b32_e64 v{{[0-9]+}}, 6
78; CI-DAG: v_lshr_b32_e64 v{{[0-9]+}}, s{{[0-9]+}}, 6
79
80; GCN-DAG: v_add_i32_e64 [[FI_ADD0:v[0-9]+]], {{s\[[0-9]+:[0-9]+\]}}, 8,
81; GCN-DAG: v_or_b32_e32 [[FI_OR0:v[0-9]+]], 4, [[FI_ADD0]]
82
83; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s5 offset:8
84; GCN-DAG: buffer_store_dword [[THIRTEEN]], off, s[0:3], s5 offset:24
85
86; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], [[FI_OR0]], s[0:3], s4 offen offset:4
87; GCN-DAG: buffer_load_dword [[LOAD1:v[0-9]+]], [[FI_OR0]], s[0:3], s4 offen offset:8
88
89; FIXME: or fails to combine with add, so FI doesn't fold and scratch wave offset is used
90; VI-DAG: v_lshrrev_b32_e64 v{{[0-9]+}}, 6
91; CI-DAG: v_lshr_b32_e64 v{{[0-9]+}}, s{{[0-9]+}}, 6
92
93; GCN-DAG: v_add_i32_e64 [[FI_ADD1:v[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, 24,
94; GCN-DAG: v_or_b32_e32 [[FI_OR1:v[0-9]+]], 4, [[FI_ADD1]]
95
96; GCN-DAG: buffer_store_dword [[LOAD0]], off, s[0:3], s32 offset:8
97; GCN-DAG: buffer_store_dword [[LOAD1]], off, s[0:3], s32 offset:12
98
99
100
101; GCN-DAG: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3], s5 offset:8
102; GCN-DAG: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3], s5 offset:12
103; GCN-DAG: buffer_store_dword [[LOAD2]], off, s[0:3], s32{{$}}
104; GCN-DAG: buffer_store_dword [[LOAD3]], off, s[0:3], s32 offset:4
105
106
107; GCN: buffer_load_dword [[LOAD4:v[0-9]+]], [[FI_OR1]], s[0:3], s4 offen offset:4
108; GCN: buffer_load_dword [[LOAD5:v[0-9]+]], [[FI_OR1]], s[0:3], s4 offen offset:8
109; GCN: buffer_store_dword [[LOAD5]], off, s[0:3], s32 offset:28
110; GCN: buffer_store_dword [[LOAD4]], off, s[0:3], s32 offset:24
111
112
113; GCN-DAG: buffer_load_dword [[LOAD6:v[0-9]+]], off, s[0:3], s5 offset:24
114; GCN-DAG: buffer_load_dword [[LOAD7:v[0-9]+]], off, s[0:3], s5 offset:28
115; GCN-DAG: buffer_store_dword [[LOAD6]], off, s[0:3], s32 offset:16
116; GCN-DAG: buffer_store_dword [[LOAD7]], off, s[0:3], s32 offset:20
117
118; GCN: s_swappc_b64
119; GCN-NEXT: s_sub_u32 s32, s32, 0x800{{$}}
120
121; GCN: v_readlane_b32
122
123; GCN: s_sub_u32 s32, s32, 0xa00{{$}}
124; GCN-NEXT: s_waitcnt
125; GCN-NEXT: s_setpc_b64
126define void @call_void_func_byval_struct_func() #0 {
127entry:
128 %arg0 = alloca %struct.ByValStruct, align 4
129 %arg1 = alloca %struct.ByValStruct, align 4
130 %tmp = bitcast %struct.ByValStruct* %arg0 to i8*
131 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp)
132 %tmp1 = bitcast %struct.ByValStruct* %arg1 to i8*
133 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp1)
134 %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg0, i32 0, i32 0, i32 0
135 store volatile i32 9, i32* %arrayidx, align 4
136 %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg1, i32 0, i32 0, i32 0
137 store volatile i32 13, i32* %arrayidx2, align 4
138 call void @void_func_byval_struct(%struct.ByValStruct* byval nonnull align 4 %arg0, %struct.ByValStruct* byval nonnull align 4 %arg1)
139 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp1)
140 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp)
141 ret void
142}
143
144; GCN-LABEL: {{^}}call_void_func_byval_struct_kernel:
145; GCN: s_mov_b32 s33, s7
146; GCN: s_add_u32 s32, s33, 0xa00{{$}}
147
148; GCN-DAG: v_mov_b32_e32 [[NINE:v[0-9]+]], 9
149; GCN-DAG: v_mov_b32_e32 [[THIRTEEN:v[0-9]+]], 13
150; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s33 offset:8
151; GCN: buffer_store_dword [[THIRTEEN]], off, s[0:3], s33 offset:24
152
153; GCN-DAG: s_add_u32 s32, s32, 0x800{{$}}
154
155; FIXME: Fold offset
156; GCN-DAG: v_or_b32_e32 [[OR_FI0:v[0-9]+]], 4,
157
158; GCN: buffer_load_dword [[LOAD0:v[0-9]+]], [[OR_FI0]], s[0:3], s33 offen offset:4
159; GCN: buffer_load_dword [[LOAD1:v[0-9]+]], [[OR_FI0]], s[0:3], s33 offen offset:8
160
161; FIXME: Fold offset
162; GCN-DAG: v_or_b32_e32 [[OR_FI1:v[0-9]+]], 4,
163
164; GCN: buffer_store_dword [[LOAD1]], off, s[0:3], s32 offset:12
165; GCN: buffer_store_dword [[LOAD0]], off, s[0:3], s32 offset:8
166
167
168; GCN-DAG: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3], s33 offset:8
169; GCN-DAG: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3], s33 offset:12
170; GCN: buffer_store_dword [[LOAD3]], off, s[0:3], s32 offset:4
171; GCN: buffer_store_dword [[LOAD2]], off, s[0:3], s32{{$}}
172
173
174
175; GCN: buffer_load_dword [[LOAD4:v[0-9]+]], [[OR_FI1]], s[0:3], s33 offen offset:4
176; GCN: buffer_load_dword [[LOAD5:v[0-9]+]], [[OR_FI1]], s[0:3], s33 offen offset:8
177; GCN: buffer_store_dword [[LOAD5]], off, s[0:3], s32 offset:28
178; GCN: buffer_store_dword [[LOAD4]], off, s[0:3], s32 offset:24
179
180
181; GCN-DAG: buffer_load_dword [[LOAD6:v[0-9]+]], off, s[0:3], s33 offset:24
182; GCN-DAG: buffer_load_dword [[LOAD7:v[0-9]+]], off, s[0:3], s33 offset:28
183; GCN-DAG: buffer_store_dword [[LOAD6]], off, s[0:3], s32 offset:16
184; GCN-DAG: buffer_store_dword [[LOAD7]], off, s[0:3], s32 offset:20
185
186
187; GCN: s_swappc_b64
188; FIXME: Dead SP modfication
189; GCN-NEXT: s_sub_u32 s32, s32, 0x800{{$}}
190; GCN-NEXT: s_endpgm
191define amdgpu_kernel void @call_void_func_byval_struct_kernel() #0 {
192entry:
193 %arg0 = alloca %struct.ByValStruct, align 4
194 %arg1 = alloca %struct.ByValStruct, align 4
195 %tmp = bitcast %struct.ByValStruct* %arg0 to i8*
196 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp)
197 %tmp1 = bitcast %struct.ByValStruct* %arg1 to i8*
198 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp1)
199 %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg0, i32 0, i32 0, i32 0
200 store volatile i32 9, i32* %arrayidx, align 4
201 %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg1, i32 0, i32 0, i32 0
202 store volatile i32 13, i32* %arrayidx2, align 4
203 call void @void_func_byval_struct(%struct.ByValStruct* byval nonnull align 4 %arg0, %struct.ByValStruct* byval nonnull align 4 %arg1)
204 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp1)
205 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp)
206 ret void
207}
208
209; GCN-LABEL: {{^}}call_void_func_byval_struct_kernel_no_frame_pointer_elim:
210define amdgpu_kernel void @call_void_func_byval_struct_kernel_no_frame_pointer_elim() #2 {
211entry:
212 %arg0 = alloca %struct.ByValStruct, align 4
213 %arg1 = alloca %struct.ByValStruct, align 4
214 %tmp = bitcast %struct.ByValStruct* %arg0 to i8*
215 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp)
216 %tmp1 = bitcast %struct.ByValStruct* %arg1 to i8*
217 call void @llvm.lifetime.start.p0i8(i64 32, i8* %tmp1)
218 %arrayidx = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg0, i32 0, i32 0, i32 0
219 store volatile i32 9, i32* %arrayidx, align 4
220 %arrayidx2 = getelementptr inbounds %struct.ByValStruct, %struct.ByValStruct* %arg1, i32 0, i32 0, i32 0
221 store volatile i32 13, i32* %arrayidx2, align 4
222 call void @void_func_byval_struct(%struct.ByValStruct* byval nonnull align 4 %arg0, %struct.ByValStruct* byval nonnull align 4 %arg1)
223 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp1)
224 call void @llvm.lifetime.end.p0i8(i64 32, i8* %tmp)
225 ret void
226}
227
228declare void @external_void_func_void() #0
229
230declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #3
231declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #3
232
233attributes #0 = { nounwind }
234attributes #1 = { noinline norecurse nounwind }
235attributes #2 = { nounwind norecurse "no-frame-pointer-elim"="true" }