Skip to content

Commit b6aa028

Browse files
bashbaugdbudanov-cmplr
authored andcommitted
Add support for split barriers extension SPV_INTEL_split_barrier (#1424)
This PR adds support for split barriers and the SPV_INTEL_split_barrier extension. The related SPIR-V extension spec can be found here: * KhronosGroup/SPIRV-Registry#136 The related OpenCL C extension spec can be found here: * KhronosGroup/OpenCL-Docs#765 Original commit: KhronosGroup/SPIRV-LLVM-Translator@e3cd296
1 parent ee0eea2 commit b6aa028

16 files changed

+571
-2
lines changed

llvm-spirv/include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ EXT(SPV_INTEL_hw_thread_queries)
5353
EXT(SPV_INTEL_global_variable_decorations)
5454
EXT(SPV_INTEL_non_constant_addrspace_printf)
5555
EXT(SPV_INTEL_complex_float_mul_div)
56+
EXT(SPV_INTEL_split_barrier)

llvm-spirv/lib/SPIRV/OCLToSPIRV.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,10 @@ void OCLToSPIRVBase::visitCallInst(CallInst &CI) {
379379
visitSubgroupImageMediaBlockINTEL(&CI, DemangledName);
380380
return;
381381
}
382+
if (DemangledName.find(kOCLBuiltinName::SplitBarrierINTELPrefix) == 0) {
383+
visitCallSplitBarrierINTEL(&CI, DemangledName);
384+
return;
385+
}
382386
// Handle 'cl_intel_device_side_avc_motion_estimation' extension built-ins
383387
if (DemangledName.find(kOCLSubgroupsAVCIntel::Prefix) == 0 ||
384388
// Workaround for a bug in the extension specification
@@ -1870,6 +1874,37 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler(
18701874
&Attrs);
18711875
}
18721876

1877+
void OCLToSPIRVBase::visitCallSplitBarrierINTEL(CallInst *CI,
1878+
StringRef DemangledName) {
1879+
auto Lit = getBarrierLiterals(CI);
1880+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
1881+
Op OpCode =
1882+
StringSwitch<Op>(DemangledName)
1883+
.Case("intel_work_group_barrier_arrive", OpControlBarrierArriveINTEL)
1884+
.Case("intel_work_group_barrier_wait", OpControlBarrierWaitINTEL)
1885+
.Default(OpNop);
1886+
1887+
mutateCallInstSPIRV(
1888+
M, CI,
1889+
[=](CallInst *, std::vector<Value *> &Args) {
1890+
Args.resize(3);
1891+
// Execution scope
1892+
Args[0] = addInt32(map<Scope>(std::get<2>(Lit)));
1893+
// Memory scope
1894+
Args[1] = addInt32(map<Scope>(std::get<1>(Lit)));
1895+
// Memory semantics
1896+
// OpControlBarrierArriveINTEL -> Release,
1897+
// OpControlBarrierWaitINTEL -> Acquire
1898+
unsigned MemFenceFlag = std::get<0>(Lit);
1899+
OCLMemOrderKind MemOrder = OpCode == OpControlBarrierArriveINTEL
1900+
? OCLMO_release
1901+
: OCLMO_acquire;
1902+
Args[2] = addInt32(mapOCLMemSemanticToSPIRV(MemFenceFlag, MemOrder));
1903+
return getSPIRVFuncName(OpCode);
1904+
},
1905+
&Attrs);
1906+
}
1907+
18731908
void OCLToSPIRVBase::visitCallLdexp(CallInst *CI, StringRef MangledName,
18741909
StringRef DemangledName) {
18751910
auto Args = getArguments(CI);

llvm-spirv/lib/SPIRV/OCLToSPIRV.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class OCLToSPIRVBase : public InstVisitor<OCLToSPIRVBase> {
247247
void visitSubgroupAVCBuiltinCallWithSampler(CallInst *CI,
248248
StringRef DemangledName);
249249

250+
/// For cl_intel_split_work_group_barrier built-ins:
251+
void visitCallSplitBarrierINTEL(CallInst *CI, StringRef DemangledName);
252+
250253
void visitCallLdexp(CallInst *CI, StringRef MangledName,
251254
StringRef DemangledName);
252255

llvm-spirv/lib/SPIRV/OCLUtil.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ template <> void SPIRVMap<std::string, Op, SPIRVInstruction>::init() {
424424
_SPIRV_OP(bitfield_extract_signed, BitFieldSExtract)
425425
_SPIRV_OP(bitfield_extract_unsigned, BitFieldUExtract)
426426
_SPIRV_OP(bit_reverse, BitReverse)
427+
// cl_khr_split_work_group_barrier
428+
_SPIRV_OP(intel_work_group_barrier_arrive, ControlBarrierArriveINTEL)
429+
_SPIRV_OP(intel_work_group_barrier_wait, ControlBarrierWaitINTEL)
427430
#undef _SPIRV_OP
428431
}
429432

@@ -1030,7 +1033,9 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
10301033
} else if (NameRef.contains("barrier")) {
10311034
addUnsignedArg(0);
10321035
if (NameRef.equals("work_group_barrier") ||
1033-
NameRef.equals("sub_group_barrier"))
1036+
NameRef.equals("sub_group_barrier") ||
1037+
NameRef.equals("intel_work_group_barrier_arrive") ||
1038+
NameRef.equals("intel_work_group_barrier_wait"))
10341039
setEnumArg(1, SPIR::PRIMITIVE_MEMORY_SCOPE);
10351040
} else if (NameRef.startswith("atomic_work_item_fence")) {
10361041
addUnsignedArg(0);

llvm-spirv/lib/SPIRV/OCLUtil.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ const static char SubgroupBlockWriteINTELPrefix[] =
305305
"intel_sub_group_block_write";
306306
const static char SubgroupImageMediaBlockINTELPrefix[] =
307307
"intel_sub_group_media_block";
308+
const static char SplitBarrierINTELPrefix[] = "intel_work_group_barrier_";
308309
const static char LDEXP[] = "ldexp";
309310
#define _SPIRV_OP(x) \
310311
const static char ConvertBFloat16##x##AsUShort##x[] = \

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,7 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
30773077
Func->addFnAttr(Attribute::NoUnwind);
30783078
auto OC = BI->getOpCode();
30793079
if (isGroupOpCode(OC) || isIntelSubgroupOpCode(OC) ||
3080-
OC == OpControlBarrier)
3080+
isSplitBarrierINTELOpCode(OC) || OC == OpControlBarrier)
30813081
Func->addFnAttr(Attribute::Convergent);
30823082
}
30833083
auto Call =

llvm-spirv/lib/SPIRV/SPIRVToOCL.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ void SPIRVToOCLBase::visitCallInst(CallInst &CI) {
119119
if (OC == OpControlBarrier) {
120120
visitCallSPIRVControlBarrier(&CI);
121121
}
122+
if (isSplitBarrierINTELOpCode(OC)) {
123+
visitCallSPIRVSplitBarrierINTEL(&CI, OC);
124+
return;
125+
}
122126
if (isAtomicOpCode(OC)) {
123127
visitCallSPIRVAtomicBuiltin(&CI, OC);
124128
return;

llvm-spirv/lib/SPIRV/SPIRVToOCL.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ class SPIRVToOCLBase : public InstVisitor<SPIRVToOCLBase> {
222222
/// - OCL1.2: barrier
223223
virtual void visitCallSPIRVControlBarrier(CallInst *CI) = 0;
224224

225+
/// Transform split __spirv_ControlBarrierArriveINTEL and
226+
/// __spirv_ControlBarrierWaitINTEL barrier to:
227+
/// - OCL2.0: overload with a memory_scope argument
228+
/// - OCL1.2: overload with no memory_scope argument
229+
virtual void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) = 0;
230+
225231
/// Transform __spirv_EnqueueKernel to __enqueue_kernel
226232
virtual void visitCallSPIRVEnqueueKernel(CallInst *CI, Op OC) = 0;
227233

@@ -305,6 +311,11 @@ class SPIRVToOCL12Base : public SPIRVToOCLBase {
305311
/// barrier(flag(sema))
306312
void visitCallSPIRVControlBarrier(CallInst *CI) override;
307313

314+
/// Transform split __spirv_ControlBarrierArriveINTEL and
315+
/// __spirv_ControlBarrierWaitINTEL barrier to overloads without a
316+
/// memory_scope argument.
317+
void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override;
318+
308319
/// Transform __spirv_OpAtomic functions. It firstly conduct generic
309320
/// mutations for all builtins and then mutate some of them seperately
310321
Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) override;
@@ -394,6 +405,11 @@ class SPIRVToOCL20Base : public SPIRVToOCLBase {
394405
/// sub_group_barrier(flag(sema), map(memScope))
395406
void visitCallSPIRVControlBarrier(CallInst *CI) override;
396407

408+
/// Transform split __spirv_ControlBarrierArriveINTEL and
409+
/// __spirv_ControlBarrierWaitINTEL barrier to overloads with a
410+
/// memory_scope argument.
411+
void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override;
412+
397413
/// Transform __spirv_Atomic* to atomic_*.
398414
/// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) =>
399415
/// atomic_*(generic atomic_op, ops, ..., order(sema), map(scope))

llvm-spirv/lib/SPIRV/SPIRVToOCL12.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ void SPIRVToOCL12Base::visitCallSPIRVControlBarrier(CallInst *CI) {
100100
&Attrs);
101101
}
102102

103+
void SPIRVToOCL12Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) {
104+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
105+
mutateCallInstOCL(
106+
M, CI,
107+
[=](CallInst *, std::vector<Value *> &Args) {
108+
Value *MemFenceFlags =
109+
SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI);
110+
Args.assign(1, MemFenceFlags);
111+
return OCLSPIRVBuiltinMap::rmap(OC);
112+
},
113+
&Attrs);
114+
}
115+
103116
Instruction *SPIRVToOCL12Base::visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) {
104117
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
105118
return mutateCallInstOCL(

llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ void SPIRVToOCL20Base::visitCallSPIRVControlBarrier(CallInst *CI) {
123123
&NewAttrs);
124124
}
125125

126+
void SPIRVToOCL20Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) {
127+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
128+
mutateCallInstOCL(
129+
M, CI,
130+
[=](CallInst *, std::vector<Value *> &Args) {
131+
auto GetArg = [=](unsigned I) {
132+
return cast<ConstantInt>(Args[I])->getZExtValue();
133+
};
134+
Value *MemScope =
135+
getInt32(M, rmap<OCLScopeKind>(static_cast<Scope>(GetArg(1))));
136+
Value *MemFenceFlags =
137+
SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI);
138+
139+
Args.resize(2);
140+
Args[0] = MemFenceFlags;
141+
Args[1] = MemScope;
142+
143+
return OCLSPIRVBuiltinMap::rmap(OC);
144+
},
145+
&Attrs);
146+
}
147+
126148
std::string SPIRVToOCL20Base::mapFPAtomicName(Op OC) {
127149
assert(isFPAtomicOpCode(OC) && "Not intended to handle other opcodes than "
128150
"AtomicF{Add/Min/Max}EXT!");

0 commit comments

Comments
 (0)