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