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 %}
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 %}
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
15 ; CHECK-SPIRV: OpFunction
16 ; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] Reduce
17 ; CHECK-SPIRV: OpFunctionEnd
19 ;; kernel void testWorkGroupFMax(float a, global float *res) {
20 ;; res[0] = work_group_reduce_max(a);
23 define dso_local spir_kernel void @testWorkGroupFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
25 %call = call spir_func float @_Z21work_group_reduce_maxf(float noundef %a)
26 store float %call, float addrspace(1)* %res, align 4
30 declare spir_func float @_Z21work_group_reduce_maxf(float noundef) local_unnamed_addr
32 ; CHECK-SPIRV: OpFunction
33 ; CHECK-SPIRV: %[[#]] = OpGroupFMin %[[#float]] %[[#ScopeWorkgroup]] Reduce
34 ; CHECK-SPIRV: OpFunctionEnd
36 ;; kernel void testWorkGroupFMin(float a, global float *res) {
37 ;; res[0] = work_group_reduce_min(a);
40 define dso_local spir_kernel void @testWorkGroupFMin(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
42 %call = call spir_func float @_Z21work_group_reduce_minf(float noundef %a)
43 store float %call, float addrspace(1)* %res, align 4
47 declare spir_func float @_Z21work_group_reduce_minf(float noundef) local_unnamed_addr
49 ; CHECK-SPIRV: OpFunction
50 ; CHECK-SPIRV: %[[#]] = OpGroupFAdd %[[#float]] %[[#ScopeWorkgroup]] Reduce
51 ; CHECK-SPIRV: OpFunctionEnd
53 ;; kernel void testWorkGroupFAdd(float a, global float *res) {
54 ;; res[0] = work_group_reduce_add(a);
57 define dso_local spir_kernel void @testWorkGroupFAdd(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
59 %call = call spir_func float @_Z21work_group_reduce_addf(float noundef %a)
60 store float %call, float addrspace(1)* %res, align 4
64 declare spir_func float @_Z21work_group_reduce_addf(float noundef) local_unnamed_addr
66 ; CHECK-SPIRV: OpFunction
67 ; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] InclusiveScan
68 ; CHECK-SPIRV: OpFunctionEnd
70 ;; kernel void testWorkGroupScanInclusiveFMax(float a, global float *res) {
71 ;; res[0] = work_group_scan_inclusive_max(a);
74 define dso_local spir_kernel void @testWorkGroupScanInclusiveFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
76 %call = call spir_func float @_Z29work_group_scan_inclusive_maxf(float noundef %a)
77 store float %call, float addrspace(1)* %res, align 4
81 declare spir_func float @_Z29work_group_scan_inclusive_maxf(float noundef) local_unnamed_addr
83 ; CHECK-SPIRV: OpFunction
84 ; CHECK-SPIRV: %[[#]] = OpGroupFMax %[[#float]] %[[#ScopeWorkgroup]] ExclusiveScan
85 ; CHECK-SPIRV: OpFunctionEnd
87 ;; kernel void testWorkGroupScanExclusiveFMax(float a, global float *res) {
88 ;; res[0] = work_group_scan_exclusive_max(a);
91 define dso_local spir_kernel void @testWorkGroupScanExclusiveFMax(float noundef %a, float addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
93 %call = call spir_func float @_Z29work_group_scan_exclusive_maxf(float noundef %a)
94 store float %call, float addrspace(1)* %res, align 4
98 declare spir_func float @_Z29work_group_scan_exclusive_maxf(float noundef) local_unnamed_addr
100 ; CHECK-SPIRV: OpFunction
101 ; CHECK-SPIRV: %[[#]] = OpGroupSMax %[[#int]] %[[#ScopeWorkgroup]] Reduce
102 ; CHECK-SPIRV: OpFunctionEnd
104 ;; kernel void testWorkGroupSMax(int a, global int *res) {
105 ;; res[0] = work_group_reduce_max(a);
108 define dso_local spir_kernel void @testWorkGroupSMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
110 %call = call spir_func i32 @_Z21work_group_reduce_maxi(i32 noundef %a)
111 store i32 %call, i32 addrspace(1)* %res, align 4
115 declare spir_func i32 @_Z21work_group_reduce_maxi(i32 noundef) local_unnamed_addr
117 ; CHECK-SPIRV: OpFunction
118 ; CHECK-SPIRV: %[[#]] = OpGroupSMin %[[#int]] %[[#ScopeWorkgroup]] Reduce
119 ; CHECK-SPIRV: OpFunctionEnd
121 ;; kernel void testWorkGroupSMin(int a, global int *res) {
122 ;; res[0] = work_group_reduce_min(a);
125 define dso_local spir_kernel void @testWorkGroupSMin(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
127 %call = call spir_func i32 @_Z21work_group_reduce_mini(i32 noundef %a)
128 store i32 %call, i32 addrspace(1)* %res, align 4
132 declare spir_func i32 @_Z21work_group_reduce_mini(i32 noundef) local_unnamed_addr
134 ; CHECK-SPIRV: OpFunction
135 ; CHECK-SPIRV: %[[#]] = OpGroupIAdd %[[#int]] %[[#ScopeWorkgroup]] Reduce
136 ; CHECK-SPIRV: OpFunctionEnd
138 ;; kernel void testWorkGroupIAddSigned(int a, global int *res) {
139 ;; res[0] = work_group_reduce_add(a);
142 define dso_local spir_kernel void @testWorkGroupIAddSigned(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
144 %call = call spir_func i32 @_Z21work_group_reduce_addi(i32 noundef %a)
145 store i32 %call, i32 addrspace(1)* %res, align 4
149 declare spir_func i32 @_Z21work_group_reduce_addi(i32 noundef) local_unnamed_addr
151 ; CHECK-SPIRV: OpFunction
152 ; CHECK-SPIRV: %[[#]] = OpGroupIAdd %[[#int]] %[[#ScopeWorkgroup]] Reduce
153 ; CHECK-SPIRV: OpFunctionEnd
155 ;; kernel void testWorkGroupIAddUnsigned(uint a, global uint *res) {
156 ;; res[0] = work_group_reduce_add(a);
159 define dso_local spir_kernel void @testWorkGroupIAddUnsigned(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
161 %call = call spir_func i32 @_Z21work_group_reduce_addj(i32 noundef %a)
162 store i32 %call, i32 addrspace(1)* %res, align 4
166 declare spir_func i32 @_Z21work_group_reduce_addj(i32 noundef) local_unnamed_addr
168 ; CHECK-SPIRV: OpFunction
169 ; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] Reduce
170 ; CHECK-SPIRV: OpFunctionEnd
172 ;; kernel void testWorkGroupUMax(uint a, global uint *res) {
173 ;; res[0] = work_group_reduce_max(a);
176 define dso_local spir_kernel void @testWorkGroupUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
178 %call = call spir_func i32 @_Z21work_group_reduce_maxj(i32 noundef %a)
179 store i32 %call, i32 addrspace(1)* %res, align 4
183 declare spir_func i32 @_Z21work_group_reduce_maxj(i32 noundef) local_unnamed_addr
185 ; CHECK-SPIRV: OpFunction
186 ; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeSubgroup]] Reduce
187 ; CHECK-SPIRV: OpFunctionEnd
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);
193 ;; #pragma OPENCL EXTENSION cl_khr_subgroups: disable
195 define dso_local spir_kernel void @testSubGroupUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
197 %call = call spir_func i32 @_Z20sub_group_reduce_maxj(i32 noundef %a)
198 store i32 %call, i32 addrspace(1)* %res, align 4
202 declare spir_func i32 @_Z20sub_group_reduce_maxj(i32 noundef) local_unnamed_addr
204 ; CHECK-SPIRV: OpFunction
205 ; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] InclusiveScan
206 ; CHECK-SPIRV: OpFunctionEnd
208 ;; kernel void testWorkGroupScanInclusiveUMax(uint a, global uint *res) {
209 ;; res[0] = work_group_scan_inclusive_max(a);
212 define dso_local spir_kernel void @testWorkGroupScanInclusiveUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
214 %call = call spir_func i32 @_Z29work_group_scan_inclusive_maxj(i32 noundef %a)
215 store i32 %call, i32 addrspace(1)* %res, align 4
219 declare spir_func i32 @_Z29work_group_scan_inclusive_maxj(i32 noundef) local_unnamed_addr
221 ; CHECK-SPIRV: OpFunction
222 ; CHECK-SPIRV: %[[#]] = OpGroupUMax %[[#int]] %[[#ScopeWorkgroup]] ExclusiveScan
223 ; CHECK-SPIRV: OpFunctionEnd
225 ;; kernel void testWorkGroupScanExclusiveUMax(uint a, global uint *res) {
226 ;; res[0] = work_group_scan_exclusive_max(a);
229 define dso_local spir_kernel void @testWorkGroupScanExclusiveUMax(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
231 %call = call spir_func i32 @_Z29work_group_scan_exclusive_maxj(i32 noundef %a)
232 store i32 %call, i32 addrspace(1)* %res, align 4
236 declare spir_func i32 @_Z29work_group_scan_exclusive_maxj(i32 noundef) local_unnamed_addr
238 ; CHECK-SPIRV: OpFunction
239 ; CHECK-SPIRV: %[[#]] = OpGroupUMin %[[#int]] %[[#ScopeWorkgroup]] Reduce
240 ; CHECK-SPIRV: OpFunctionEnd
242 ;; kernel void testWorkGroupUMin(uint a, global uint *res) {
243 ;; res[0] = work_group_reduce_min(a);
246 define dso_local spir_kernel void @testWorkGroupUMin(i32 noundef %a, i32 addrspace(1)* nocapture noundef writeonly %res) local_unnamed_addr {
248 %call = call spir_func i32 @_Z21work_group_reduce_minj(i32 noundef %a)
249 store i32 %call, i32 addrspace(1)* %res, align 4
253 declare spir_func i32 @_Z21work_group_reduce_minj(i32 noundef) local_unnamed_addr
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
264 ;; kernel void testWorkGroupBroadcast(uint a, global size_t *id, global int *res) {
265 ;; res[0] = work_group_broadcast(a, *id);
268 define 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 {
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)
279 declare spir_func i32 @_Z20work_group_broadcastjj(i32 noundef, i32 noundef) local_unnamed_addr
280 declare spir_func i32 @_Z20work_group_broadcastjjj(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
281 declare spir_func i32 @_Z20work_group_broadcastjjjj(i32 noundef, i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
282 declare spir_func i32 @__spirv_GroupBroadcast(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr
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
295 define spir_kernel void @foo(float %a, i32 %b) {
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)
308 declare spir_func float @__spirv_GroupFAdd(i32, i32, float)
309 declare spir_func float @__spirv_GroupFMin(i32, i32, float)
310 declare spir_func float @__spirv_GroupFMax(i32, i32, float)
311 declare spir_func i32 @__spirv_GroupIAdd(i32, i32, i32)
312 declare spir_func i32 @__spirv_GroupUMin(i32, i32, i32)
313 declare spir_func i32 @__spirv_GroupSMin(i32, i32, i32)
314 declare spir_func i32 @__spirv_GroupUMax(i32, i32, i32)
315 declare spir_func i32 @__spirv_GroupSMax(i32, i32, i32)