Skip to content

Commit 95589cf

Browse files
bashbaugjsji
authored andcommitted
initial support for SPV_INTEL_device_barrier (#3461)
Adds initial (preview) support for device scope barriers via SPV_INTEL_device_barrier. See: #12092 Original commit: KhronosGroup/SPIRV-LLVM-Translator@36a6c287e3ecbb7
1 parent bf6ba55 commit 95589cf

File tree

13 files changed

+359
-7
lines changed

13 files changed

+359
-7
lines changed

llvm-spirv/include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ EXT(SPV_INTEL_runtime_aligned)
5555
EXT(SPV_EXT_arithmetic_fence)
5656
EXT(SPV_INTEL_arithmetic_fence)
5757
EXT(SPV_INTEL_bfloat16_conversion)
58+
EXT(SPV_INTEL_device_barrier)
5859
EXT(SPV_INTEL_joint_matrix)
5960
EXT(SPV_INTEL_hw_thread_queries)
6061
EXT(SPV_INTEL_global_variable_decorations)

llvm-spirv/lib/SPIRV/SPIRVInternal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ CallInst *setAttrByCalledFunc(CallInst *Call);
10001000
bool isSPIRVBuiltinVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind *Kind);
10011001
// Transform builtin variable from GlobalVariable to builtin call.
10021002
// e.g.
1003-
// - GlobalInvolcationId[x] -> _Z33__spirv_BuiltInGlobalInvocationIdi(x)
1003+
// - GlobalInvocationId[x] -> _Z33__spirv_BuiltInGlobalInvocationIdi(x)
10041004
// - WorkDim -> _Z22__spirv_BuiltInWorkDimv()
10051005
bool lowerBuiltinVariableToCall(GlobalVariable *GV,
10061006
SPIRVBuiltinVariableKind Kind);

llvm-spirv/lib/SPIRV/SPIRVUtil.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,13 +2107,15 @@ static void replaceUsesOfBuiltinVar(Value *V, const APInt &AccumulatedOffset,
21072107
} else if (auto *Load = dyn_cast<LoadInst>(U)) {
21082108
// Figure out which index the accumulated offset corresponds to. If we
21092109
// have a weird offset (e.g., trying to load byte 7), bail out.
2110-
Type *ScalarTy = ReplacementFunc->getReturnType();
21112110
APInt Index;
2112-
uint64_t Remainder;
2113-
APInt::udivrem(AccumulatedOffset, ScalarTy->getScalarSizeInBits() / 8,
2114-
Index, Remainder);
2115-
if (Remainder != 0)
2116-
llvm_unreachable("Illegal GEP of a SPIR-V builtin variable");
2111+
Type *ScalarTy = ReplacementFunc->getReturnType();
2112+
if (!ScalarTy->isIntegerTy(1)) {
2113+
uint64_t Remainder;
2114+
APInt::udivrem(AccumulatedOffset, ScalarTy->getScalarSizeInBits() / 8,
2115+
Index, Remainder);
2116+
if (Remainder != 0)
2117+
llvm_unreachable("Illegal GEP of a SPIR-V builtin variable");
2118+
}
21172119

21182120
IRBuilder<> Builder(Load);
21192121
Value *Replacement;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,8 @@ class SPIRVCapability : public SPIRVEntryNoId<OpCapability> {
921921
return ExtensionID::SPV_INTEL_function_variants;
922922
case internal::CapabilityBFloat16ArithmeticINTEL:
923923
return ExtensionID::SPV_INTEL_bfloat16_arithmetic;
924+
case internal::CapabilityDeviceBarrierINTEL:
925+
return ExtensionID::SPV_INTEL_device_barrier;
924926
default:
925927
return {};
926928
}

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ template <> inline void SPIRVMap<BuiltIn, SPIRVCapVec>::init() {
584584
{internal::CapabilityHWThreadQueryINTEL});
585585
ADD_VEC_INIT(internal::BuiltInGlobalHWThreadIDINTEL,
586586
{internal::CapabilityHWThreadQueryINTEL});
587+
ADD_VEC_INIT(internal::BuiltInDeviceBarrierValidINTEL,
588+
{internal::CapabilityDeviceBarrierINTEL});
587589
}
588590

589591
template <> inline void SPIRVMap<MemorySemanticsMask, SPIRVCapVec>::init() {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,13 +2483,40 @@ class SPIRVControlBarrier : public SPIRVInstruction {
24832483
return getValues(Operands);
24842484
}
24852485

2486+
SPIRVCapVec getRequiredCapability() const override {
2487+
if (isDeviceBarrier()) {
2488+
return getVec(internal::CapabilityDeviceBarrierINTEL);
2489+
}
2490+
return SPIRVInstruction::getRequiredCapability();
2491+
}
2492+
std::optional<ExtensionID> getRequiredExtension() const override {
2493+
if (isDeviceBarrier()) {
2494+
return ExtensionID::SPV_INTEL_device_barrier;
2495+
}
2496+
return std::nullopt;
2497+
}
2498+
24862499
protected:
24872500
_SPIRV_DEF_ENCDEC3(ExecScope, MemScope, MemSema)
24882501
void validate() const override {
24892502
assert(OpCode == OC);
24902503
assert(WordCount == 4);
24912504
SPIRVInstruction::validate();
24922505
}
2506+
2507+
bool isDeviceBarrier() const {
2508+
if (!getModule()->isAllowedToUseExtension(
2509+
ExtensionID::SPV_INTEL_device_barrier))
2510+
return false;
2511+
SPIRVValue *ESV = getValue(ExecScope);
2512+
if (ESV && ESV->getOpCode() == OpConstant) {
2513+
if (static_cast<SPIRVConstant *>(ESV)->getZExtIntValue() != ScopeDevice) {
2514+
return false;
2515+
}
2516+
}
2517+
return true;
2518+
}
2519+
24932520
SPIRVId ExecScope;
24942521
SPIRVId MemScope = SPIRVID_INVALID;
24952522
SPIRVId MemSema = SPIRVID_INVALID;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ inline bool isValid(spv::BuiltIn V) {
282282
case BuiltInCullMaskKHR:
283283
case internal::BuiltInSubDeviceIDINTEL:
284284
case internal::BuiltInGlobalHWThreadIDINTEL:
285+
case internal::BuiltInDeviceBarrierValidINTEL:
285286
return true;
286287
default:
287288
return false;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ template <> inline void SPIRVMap<BuiltIn, std::string>::init() {
362362
add(BuiltInMax, "BuiltInMax");
363363
add(internal::BuiltInSubDeviceIDINTEL, "BuiltInSubDeviceIDINTEL");
364364
add(internal::BuiltInGlobalHWThreadIDINTEL, "BuiltInGlobalHWThreadIDINTEL");
365+
add(internal::BuiltInDeviceBarrierValidINTEL,
366+
"BuiltInDeviceBarrierValidINTEL");
365367
}
366368
SPIRV_DEF_NAMEMAP(BuiltIn, SPIRVBuiltInNameMap)
367369

@@ -705,6 +707,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
705707
add(CapabilityFloat8CooperativeMatrixEXT, "Float8CooperativeMatrixEXT");
706708
add(internal::CapabilityPredicatedIOINTEL, "PredicatedIOINTEL");
707709
add(internal::CapabilitySigmoidINTEL, "SigmoidINTEL");
710+
add(internal::CapabilityDeviceBarrierINTEL, "DeviceBarrierINTEL");
708711
add(internal::CapabilityFloat4E2M1INTEL, "Float4E2M1INTEL");
709712
add(internal::CapabilityFloat4E2M1CooperativeMatrixINTEL,
710713
"Float4E2M1CooperativeMatrixINTEL");

llvm-spirv/lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ enum InternalCapability {
105105
ICapGlobalVariableDecorationsINTEL = 6146,
106106
ICapabilityTaskSequenceINTEL = 6162,
107107
ICapabilitySigmoidINTEL = 6167,
108+
ICapabilityDeviceBarrierINTEL = 6185,
108109
ICapabilityCooperativeMatrixCheckedInstructionsINTEL = 6192,
109110
ICapabilityFloat4E2M1INTEL = 6212,
110111
ICapabilityFloat4E2M1CooperativeMatrixINTEL = 6213,
@@ -151,6 +152,7 @@ enum InternalFPEncoding {
151152
enum InternalBuiltIn {
152153
IBuiltInSubDeviceIDINTEL = 6135,
153154
IBuiltInGlobalHWThreadIDINTEL = 6136,
155+
IBuiltInDeviceBarrierValidINTEL = 6186,
154156
};
155157

156158
#define _SPIRV_OP(x, y) constexpr x x##y = static_cast<x>(I##x##y);
@@ -174,6 +176,9 @@ _SPIRV_OP(Op, CooperativeMatrixStoreOffsetINTEL)
174176
_SPIRV_OP(Capability, CooperativeMatrixInvocationInstructionsINTEL)
175177
_SPIRV_OP(Op, CooperativeMatrixApplyFunctionINTEL)
176178

179+
_SPIRV_OP(Capability, DeviceBarrierINTEL)
180+
_SPIRV_OP(BuiltIn, DeviceBarrierValidINTEL)
181+
177182
_SPIRV_OP(Capability, HWThreadQueryINTEL)
178183
_SPIRV_OP(BuiltIn, SubDeviceIDINTEL)
179184
_SPIRV_OP(BuiltIn, GlobalHWThreadIDINTEL)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
;; kernel void test(global uint* dst)
2+
;; {
3+
;; int scope = magic_get_scope();
4+
;; __spirv_ControlBarrier(scope, 1, 264); // local
5+
;; __spirv_ControlBarrier(scope, 1, 520); // global
6+
;; __spirv_ControlBarrier(scope, 1, 2056); // image
7+
;;
8+
;; __spirv_ControlBarrier(scope, 0, 520); // global, all_svm_devices
9+
;; __spirv_ControlBarrier(scope, 1, 520); // global, device
10+
;; __spirv_ControlBarrier(scope, 2, 520); // global, work_group
11+
;; __spirv_ControlBarrier(scope, 3, 520); // global, subgroup
12+
;; __spirv_ControlBarrier(scope, 4, 520); // global, work_item
13+
;;}
14+
15+
; Test for SPV_INTEL_device_barrier (SPIR-V friendly LLVM IR)
16+
; RUN: llvm-as %s -o %t.bc
17+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_device_barrier
18+
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
19+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
20+
21+
; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=SPV-IR
22+
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
23+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
24+
25+
; RUN: llvm-spirv %t.bc -o %t.disabled.spv
26+
; RUN: llvm-spirv %t.disabled.spv -o %t.disabled.spt --to-text
27+
; RUN: FileCheck < %t.disabled.spt %s --check-prefix=CHECK-SPIRV-EXTENSION-DISABLED
28+
29+
; ModuleID = 'device_barrier_spirv.cl'
30+
source_filename = "device_barrier_spirv.cl"
31+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
32+
target triple = "spir64"
33+
34+
; CHECK-SPIRV: Capability DeviceBarrierINTEL
35+
; CHECK-SPIRV: Extension "SPV_INTEL_device_barrier"
36+
; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0
37+
;
38+
;; When the SPV_INTEL_device_barrier extension is not enabled, a runtime variable
39+
;; should not cause the device barrier extension or capability to be declared.
40+
; CHECK-SPIRV-EXTENSION-DISABLED-NOT: Capability DeviceBarrierINTEL
41+
; CHECK-SPIRV-EXTENSION-DISABLED-NOT: Extension "SPV_INTEL_device_barrier"
42+
;
43+
; Scopes:
44+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_CROSS_DEVICE:[0-9]+]] 0 {{$}}
45+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_DEVICE:[0-9]+]] 1 {{$}}
46+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2 {{$}}
47+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_SUBGROUP:[0-9]+]] 3 {{$}}
48+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_INVOCATION:[0-9]+]] 4 {{$}}
49+
;
50+
; Memory Semantics:
51+
; 0x8 AcquireRelease + 0x100 WorkgroupMemory
52+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQREL_LOCAL:[0-9]+]] 264
53+
; 0x8 AcquireRelease + 0x200 CrossWorkgroupMemory
54+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQREL_GLOBAL:[0-9]+]] 520
55+
; 0x8 AcquireRelease + 0x800 ImageMemory
56+
; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQREL_IMAGE:[0-9]+]] 2056
57+
;
58+
; Runtime execution scope:
59+
; CHECK-SPIRV: FunctionCall [[#]] [[EXEC_SCOPE:[0-9]+]] [[#]]
60+
;
61+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_DEVICE]] [[ACQREL_LOCAL]]
62+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_DEVICE]] [[ACQREL_GLOBAL]]
63+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_DEVICE]] [[ACQREL_IMAGE]]
64+
;
65+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_CROSS_DEVICE]] [[ACQREL_GLOBAL]]
66+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_DEVICE]] [[ACQREL_GLOBAL]]
67+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_WORK_GROUP]] [[ACQREL_GLOBAL]]
68+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_SUBGROUP]] [[ACQREL_GLOBAL]]
69+
; CHECK-SPIRV: ControlBarrier [[EXEC_SCOPE]] [[SCOPE_INVOCATION]] [[ACQREL_GLOBAL]]
70+
71+
; CHECK-LLVM-LABEL: define spir_kernel void @test
72+
; Function Attrs: convergent norecurse nounwind
73+
define dso_local spir_kernel void @test(ptr addrspace(1) captures(none) noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
74+
%2 = call noundef i32 @magic_get_scope()
75+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 1, i32 noundef 264) #2
76+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 1, i32 264) #1
77+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 1, i32 noundef 520) #2
78+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 1, i32 520) #1
79+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 1, i32 noundef 2056) #2
80+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 1, i32 2056) #1
81+
82+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 0, i32 noundef 520) #2
83+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 0, i32 520) #1
84+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 1, i32 noundef 520) #2
85+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 1, i32 520) #1
86+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 2, i32 noundef 520) #2
87+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 2, i32 520) #1
88+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 3, i32 noundef 520) #2
89+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 3, i32 520) #1
90+
tail call spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef %2, i32 noundef 4, i32 noundef 520) #2
91+
; CHECK-LLVM: call spir_func void @_Z22__spirv_ControlBarrieriii(i32 %2, i32 4, i32 520) #1
92+
ret void
93+
}
94+
95+
; Function Attrs: convergent
96+
declare dso_local spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1
97+
98+
declare spir_func i32 @magic_get_scope()
99+
100+
attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" }
101+
attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
102+
attributes #2 = { convergent nounwind }
103+
104+
!llvm.module.flags = !{!0, !1}
105+
!opencl.ocl.version = !{!2}
106+
!opencl.spir.version = !{!2}
107+
!llvm.ident = !{!3}
108+
109+
!0 = !{i32 1, !"wchar_size", i32 4}
110+
!1 = !{i32 7, !"frame-pointer", i32 2}
111+
!2 = !{i32 2, i32 0}
112+
!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"}
113+
!4 = !{i32 1}
114+
!5 = !{!"none"}
115+
!6 = !{!"uint*"}
116+
!7 = !{!""}

0 commit comments

Comments
 (0)