xref: /llvm-project/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll (revision 2fc7a72733762d685a07f846b44dc17a0585098e)
1; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
2; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3
4; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
5; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
6
7; CHECK-SPIRV-DAG: %[[#int:]] = OpTypeInt 32 0
8; CHECK-SPIRV-DAG: %[[#intv2:]] = OpTypeVector %[[#int]] 2
9; CHECK-SPIRV-DAG: %[[#intv3:]] = OpTypeVector %[[#int]] 3
10; CHECK-SPIRV-DAG: %[[#float:]] = OpTypeFloat 32
11; CHECK-SPIRV-DAG: %[[#ScopeCrossWorkgroup:]] = OpConstant %[[#int]] 0
12; CHECK-SPIRV-DAG: %[[#ScopeWorkgroup:]] = OpConstant %[[#int]] 2
13; CHECK-SPIRV-DAG: %[[#ScopeSubgroup:]] = OpConstant %[[#int]] 3
14
15; CHECK-SPIRV: OpFunction
16; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] Reduce
17; CHECK-SPIRV: OpFunctionEnd
18
19;; kernel void testWorkGroupFMax(float a, global float *res) {
20;;   res[0] = work_group_reduce_max(a);
21;; }
22
23define dso_local spir_kernel void @testWorkGroupFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
24entry:
25  %call = call spir_func float @_Z21work_group_reduce_maxf(float noundef %a)
26  store float %call, float addrspace(1)* %res, align 4
27  ret void
28}
29
30declare spir_func float @_Z21work_group_reduce_maxf(float noundef) local_unnamed_addr
31
32; CHECK-SPIRV: OpFunction
33; CHECK-SPIRV: %[[#]] = OpGroupFMin %[[#float]] %[[#ScopeWorkgroup]] Reduce
34; CHECK-SPIRV: OpFunctionEnd
35
36;; kernel void testWorkGroupFMin(float a, global float *res) {
37;;   res[0] = work_group_reduce_min(a);
38;; }
39
40define dso_local spir_kernel void @testWorkGroupFMin(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
41entry:
42  %call = call spir_func float @_Z21work_group_reduce_minf(float noundef %a)
43  store float %call, float addrspace(1)* %res, align 4
44  ret void
45}
46
47declare spir_func float @_Z21work_group_reduce_minf(float noundef) local_unnamed_addr
48
49; CHECK-SPIRV: OpFunction
50; CHECK-SPIRV: %[[#]] = OpGroupFAdd %[[#float]] %[[#ScopeWorkgroup]] Reduce
51; CHECK-SPIRV: OpFunctionEnd
52
53;; kernel void testWorkGroupFAdd(float a, global float *res) {
54;;   res[0] = work_group_reduce_add(a);
55;; }
56
57define dso_local spir_kernel void @testWorkGroupFAdd(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
58entry:
59  %call = call spir_func float @_Z21work_group_reduce_addf(float noundef %a)
60  store float %call, float addrspace(1)* %res, align 4
61  ret void
62}
63
64declare spir_func float @_Z21work_group_reduce_addf(float noundef) local_unnamed_addr
65
66; CHECK-SPIRV: OpFunction
67; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] InclusiveScan
68; CHECK-SPIRV: OpFunctionEnd
69
70;; kernel void testWorkGroupScanInclusiveFMax(float a, global float *res) {
71;;   res[0] = work_group_scan_inclusive_max(a);
72;; }
73
74define dso_local spir_kernel void @testWorkGroupScanInclusiveFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
75entry:
76  %call = call spir_func float @_Z29work_group_scan_inclusive_maxf(float noundef %a)
77  store float %call, float addrspace(1)* %res, align 4
78  ret void
79}
80
81declare spir_func float @_Z29work_group_scan_inclusive_maxf(float noundef) local_unnamed_addr
82
83; CHECK-SPIRV: OpFunction
84; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] ExclusiveScan
85; CHECK-SPIRV: OpFunctionEnd
86
87;; kernel void testWorkGroupScanExclusiveFMax(float a, global float *res) {
88;;   res[0] = work_group_scan_exclusive_max(a);
89;; }
90
91define dso_local spir_kernel void @testWorkGroupScanExclusiveFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
92entry:
93  %call = call spir_func float @_Z29work_group_scan_exclusive_maxf(float noundef %a)
94  store float %call, float addrspace(1)* %res, align 4
95  ret void
96}
97
98declare spir_func float @_Z29work_group_scan_exclusive_maxf(float noundef) local_unnamed_addr
99
100; CHECK-SPIRV: OpFunction
101; CHECK-SPIRV: %[[#]] = OpGroupSMax %[[#int]] %[[#ScopeWorkgroup]] Reduce
102; CHECK-SPIRV: OpFunctionEnd
103
104;; kernel void testWorkGroupSMax(int a, global int *res) {
105;;   res[0] = work_group_reduce_max(a);
106;; }
107
108define dso_local spir_kernel void @testWorkGroupSMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
109entry:
110  %call = call spir_func i32 @_Z21work_group_reduce_maxi(i32 noundef %a)
111  store i32 %call, i32 addrspace(1)* %res, align 4
112  ret void
113}
114
115declare spir_func i32 @_Z21work_group_reduce_maxi(i32 noundef) local_unnamed_addr
116
117; CHECK-SPIRV: OpFunction
118; CHECK-SPIRV: %[[#]] = OpGroupSMin %[[#int]] %[[#ScopeWorkgroup]] Reduce
119; CHECK-SPIRV: OpFunctionEnd
120
121;; kernel void testWorkGroupSMin(int a, global int *res) {
122;;   res[0] = work_group_reduce_min(a);
123;; }
124
125define dso_local spir_kernel void @testWorkGroupSMin(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
126entry:
127  %call = call spir_func i32 @_Z21work_group_reduce_mini(i32 noundef %a)
128  store i32 %call, i32 addrspace(1)* %res, align 4
129  ret void
130}
131
132declare spir_func i32 @_Z21work_group_reduce_mini(i32 noundef) local_unnamed_addr
133
134; CHECK-SPIRV: OpFunction
135; CHECK-SPIRV: %[[#]] = OpGroupIAdd %[[#int]] %[[#ScopeWorkgroup]] Reduce
136; CHECK-SPIRV: OpFunctionEnd
137
138;; kernel void testWorkGroupIAddSigned(int a, global int *res) {
139;;   res[0] = work_group_reduce_add(a);
140;; }
141
142define dso_local spir_kernel void @testWorkGroupIAddSigned(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
143entry:
144  %call = call spir_func i32 @_Z21work_group_reduce_addi(i32 noundef %a)
145  store i32 %call, i32 addrspace(1)* %res, align 4
146  ret void
147}
148
149declare spir_func i32 @_Z21work_group_reduce_addi(i32 noundef) local_unnamed_addr
150
151; CHECK-SPIRV: OpFunction
152; CHECK-SPIRV: %[[#]] = OpGroupIAdd %[[#int]] %[[#ScopeWorkgroup]] Reduce
153; CHECK-SPIRV: OpFunctionEnd
154
155;; kernel void testWorkGroupIAddUnsigned(uint a, global uint *res) {
156;;   res[0] = work_group_reduce_add(a);
157;; }
158
159define dso_local spir_kernel void @testWorkGroupIAddUnsigned(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
160entry:
161  %call = call spir_func i32 @_Z21work_group_reduce_addj(i32 noundef %a)
162  store i32 %call, i32 addrspace(1)* %res, align 4
163  ret void
164}
165
166declare spir_func i32 @_Z21work_group_reduce_addj(i32 noundef) local_unnamed_addr
167
168; CHECK-SPIRV: OpFunction
169; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] Reduce
170; CHECK-SPIRV: OpFunctionEnd
171
172;; kernel void testWorkGroupUMax(uint a, global uint *res) {
173;;   res[0] = work_group_reduce_max(a);
174;; }
175
176define dso_local spir_kernel void @testWorkGroupUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
177entry:
178  %call = call spir_func i32 @_Z21work_group_reduce_maxj(i32 noundef %a)
179  store i32 %call, i32 addrspace(1)* %res, align 4
180  ret void
181}
182
183declare spir_func i32 @_Z21work_group_reduce_maxj(i32 noundef) local_unnamed_addr
184
185; CHECK-SPIRV: OpFunction
186; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeSubgroup]] Reduce
187; CHECK-SPIRV: OpFunctionEnd
188
189;; #pragma OPENCL EXTENSION cl_khr_subgroups: enable
190;; kernel void testSubGroupUMax(uint a, global uint *res) {
191;;   res[0] = sub_group_reduce_max(a);
192;; }
193;; #pragma OPENCL EXTENSION cl_khr_subgroups: disable
194
195define dso_local spir_kernel void @testSubGroupUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
196entry:
197  %call = call spir_func i32 @_Z20sub_group_reduce_maxj(i32 noundef %a)
198  store i32 %call, i32 addrspace(1)* %res, align 4
199  ret void
200}
201
202declare spir_func i32 @_Z20sub_group_reduce_maxj(i32 noundef) local_unnamed_addr
203
204; CHECK-SPIRV: OpFunction
205; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] InclusiveScan
206; CHECK-SPIRV: OpFunctionEnd
207
208;; kernel void testWorkGroupScanInclusiveUMax(uint a, global uint *res) {
209;;   res[0] = work_group_scan_inclusive_max(a);
210;; }
211
212define dso_local spir_kernel void @testWorkGroupScanInclusiveUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
213entry:
214  %call = call spir_func i32 @_Z29work_group_scan_inclusive_maxj(i32 noundef %a)
215  store i32 %call, i32 addrspace(1)* %res, align 4
216  ret void
217}
218
219declare spir_func i32 @_Z29work_group_scan_inclusive_maxj(i32 noundef) local_unnamed_addr
220
221; CHECK-SPIRV: OpFunction
222; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] ExclusiveScan
223; CHECK-SPIRV: OpFunctionEnd
224
225;; kernel void testWorkGroupScanExclusiveUMax(uint a, global uint *res) {
226;;   res[0] = work_group_scan_exclusive_max(a);
227;; }
228
229define dso_local spir_kernel void @testWorkGroupScanExclusiveUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
230entry:
231  %call = call spir_func i32 @_Z29work_group_scan_exclusive_maxj(i32 noundef %a)
232  store i32 %call, i32 addrspace(1)* %res, align 4
233  ret void
234}
235
236declare spir_func i32 @_Z29work_group_scan_exclusive_maxj(i32 noundef) local_unnamed_addr
237
238; CHECK-SPIRV: OpFunction
239; CHECK-SPIRV: %[[#]] = OpGroupUMin %[[#int]] %[[#ScopeWorkgroup]] Reduce
240; CHECK-SPIRV: OpFunctionEnd
241
242;; kernel void testWorkGroupUMin(uint a, global uint *res) {
243;;   res[0] = work_group_reduce_min(a);
244;; }
245
246define dso_local spir_kernel void @testWorkGroupUMin(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
247entry:
248  %call = call spir_func i32 @_Z21work_group_reduce_minj(i32 noundef %a)
249  store i32 %call, i32 addrspace(1)* %res, align 4
250  ret void
251}
252
253declare spir_func i32 @_Z21work_group_reduce_minj(i32 noundef) local_unnamed_addr
254
255; CHECK-SPIRV: OpFunction
256; CHECK-SPIRV: %[[#]] = OpGroupBroadcast %[[#int]] %[[#ScopeWorkgroup]] %[[#BroadcastValue:]] %[[#BroadcastLocalId:]]
257; CHECK-SPIRV: %[[#BroadcastVec2:]] = OpCompositeConstruct %[[#intv2]] %[[#BroadcastLocalId]] %[[#BroadcastLocalId]]
258; CHECK-SPIRV: %[[#]] = OpGroupBroadcast %[[#int]] %[[#ScopeWorkgroup]] %[[#BroadcastValue]] %[[#BroadcastVec2]]
259; CHECK-SPIRV: %[[#BroadcastVec3:]] = OpCompositeConstruct %[[#intv3]] %[[#BroadcastLocalId]] %[[#BroadcastLocalId]] %[[#BroadcastLocalId]]
260; CHECK-SPIRV: %[[#]] = OpGroupBroadcast %[[#int]] %[[#ScopeWorkgroup]] %[[#BroadcastValue]] %[[#BroadcastVec3]]
261; CHECK-SPIRV: %[[#]] = OpGroupBroadcast %[[#int]] %[[#ScopeCrossWorkgroup]] %[[#BroadcastValue]] %[[#BroadcastLocalId]]
262; CHECK-SPIRV: OpFunctionEnd
263
264;; kernel void testWorkGroupBroadcast(uint a, global size_t *id, global int *res) {
265;;   res[0] = work_group_broadcast(a, *id);
266;; }
267
268define dso_local spir_kernel void @testWorkGroupBroadcast(i32 noundef %a, i32 addrspace(1)* nocapture noundef readonly %id, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
269entry:
270  %0 = load i32, i32 addrspace(1)* %id, align 4
271  %call = call spir_func i32 @_Z20work_group_broadcastjj(i32 noundef %a, i32 noundef %0)
272  %call_v2 = call spir_func i32 @_Z20work_group_broadcastjj(i32 noundef %a, i32 noundef %0, i32 noundef %0)
273  %call_v3 = call spir_func i32 @_Z20work_group_broadcastjj(i32 noundef %a, i32 noundef %0, i32 noundef %0, i32 noundef %0)
274  store i32 %call, i32 addrspace(1)* %res, align 4
275  %call1 = call spir_func i32 @__spirv_GroupBroadcast(i32 0, i32 noundef %a, i32 noundef %0)
276  ret void
277}
278
279declare spir_func i32 @_Z20work_group_broadcastjj(i32 noundef, i32 noundef) local_unnamed_addr
280declare spir_func i32 @_Z20work_group_broadcastjjj(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
281declare spir_func i32 @_Z20work_group_broadcastjjjj(i32 noundef, i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
282declare spir_func i32 @__spirv_GroupBroadcast(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
283
284; CHECK-SPIRV: OpFunction
285; CHECK-SPIRV: %[[#]] = OpGroupFAdd %[[#float]] %[[#ScopeCrossWorkgroup]] Reduce %[[#FValue:]]
286; CHECK-SPIRV: %[[#]] = OpGroupFMin %[[#float]] %[[#ScopeWorkgroup]] InclusiveScan %[[#FValue]]
287; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeSubgroup]] ExclusiveScan %[[#FValue]]
288; CHECK-SPIRV: %[[#]] = OpGroupIAdd %[[#int]] %[[#ScopeCrossWorkgroup]] Reduce %[[#IValue:]]
289; CHECK-SPIRV: %[[#]] = OpGroupUMin %[[#int]] %[[#ScopeWorkgroup]] InclusiveScan %[[#IValue]]
290; CHECK-SPIRV: %[[#]] = OpGroupSMin %[[#int]] %[[#ScopeSubgroup]] ExclusiveScan %[[#IValue]]
291; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeCrossWorkgroup]] Reduce %[[#IValue]]
292; CHECK-SPIRV: %[[#]] = OpGroupSMax %[[#int]] %[[#ScopeWorkgroup]] InclusiveScan %[[#IValue]]
293; CHECK-SPIRV: OpFunctionEnd
294
295define spir_kernel void @foo(float %a, i32 %b) {
296entry:
297  %f1 = call spir_func float @__spirv_GroupFAdd(i32 0, i32 0, float %a)
298  %f2 = call spir_func float @__spirv_GroupFMin(i32 2, i32 1, float %a)
299  %f3 = call spir_func float @__spirv_GroupFMax(i32 3, i32 2, float %a)
300  %i1 = call spir_func i32 @__spirv_GroupIAdd(i32 0, i32 0, i32 %b)
301  %i2 = call spir_func i32 @__spirv_GroupUMin(i32 2, i32 1, i32 %b)
302  %i3 = call spir_func i32 @__spirv_GroupSMin(i32 3, i32 2, i32 %b)
303  %i4 = call spir_func i32 @__spirv_GroupUMax(i32 0, i32 0, i32 %b)
304  %i5 = call spir_func i32 @__spirv_GroupSMax(i32 2, i32 1, i32 %b)
305  ret void
306}
307
308declare spir_func float @__spirv_GroupFAdd(i32, i32, float)
309declare spir_func float @__spirv_GroupFMin(i32, i32, float)
310declare spir_func float @__spirv_GroupFMax(i32, i32, float)
311declare spir_func i32 @__spirv_GroupIAdd(i32, i32, i32)
312declare spir_func i32 @__spirv_GroupUMin(i32, i32, i32)
313declare spir_func i32 @__spirv_GroupSMin(i32, i32, i32)
314declare spir_func i32 @__spirv_GroupUMax(i32, i32, i32)
315declare spir_func i32 @__spirv_GroupSMax(i32, i32, i32)
316