Skip to content

Commit

Permalink
Initialize mem fence passing to barrier in runtime if necessary
Browse files Browse the repository at this point in the history
If a flag passed to ControlBarrier or MemoryBarrier is being
initialized in runtime - don't lose it's initialization.

Signed-off-by: Dmitry Sidorov <[email protected]>
  • Loading branch information
MrSidims authored and svenvh committed Aug 1, 2019
1 parent 4abd17a commit 7a53bfb
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 12 deletions.
31 changes: 31 additions & 0 deletions lib/SPIRV/OCLUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ enum OCLMemFenceKind {
OCLMF_Image = 4,
};

// This enum declares extra constants for OpenCL mem_fence flag. It includes
// combinations of local/global/image flags.
enum OCLMemFenceExtendedKind {
OCLMFEx_Local = OCLMF_Local,
OCLMFEx_Global = OCLMF_Global,
OCLMFEx_Local_Global = OCLMF_Global | OCLMF_Local,
OCLMFEx_Image = OCLMF_Image,
OCLMFEx_Image_Local = OCLMF_Image | OCLMF_Local,
OCLMFEx_Image_Global = OCLMF_Image | OCLMF_Global,
OCLMFEx_Image_Local_Global = OCLMF_Image | OCLMF_Global | OCLMF_Local,
};

enum OCLScopeKind {
OCLMS_work_item,
OCLMS_work_group,
Expand Down Expand Up @@ -95,6 +107,9 @@ enum OCLMemOrderKind {

typedef SPIRVMap<OCLMemFenceKind, MemorySemanticsMask> OCLMemFenceMap;

typedef SPIRVMap<OCLMemFenceExtendedKind, MemorySemanticsMask>
OCLMemFenceExtendedMap;

typedef SPIRVMap<OCLMemOrderKind, unsigned, MemorySemanticsMask> OCLMemOrderMap;

typedef SPIRVMap<OCLScopeKind, Scope> OCLMemScopeMap;
Expand Down Expand Up @@ -425,6 +440,22 @@ template <> inline void SPIRVMap<OCLMemFenceKind, MemorySemanticsMask>::init() {
add(OCLMF_Image, MemorySemanticsImageMemoryMask);
}

template <>
inline void SPIRVMap<OCLMemFenceExtendedKind, MemorySemanticsMask>::init() {
add(OCLMFEx_Local, MemorySemanticsWorkgroupMemoryMask);
add(OCLMFEx_Global, MemorySemanticsCrossWorkgroupMemoryMask);
add(OCLMFEx_Local_Global, MemorySemanticsWorkgroupMemoryMask |
MemorySemanticsCrossWorkgroupMemoryMask);
add(OCLMFEx_Image, MemorySemanticsImageMemoryMask);
add(OCLMFEx_Image_Local,
MemorySemanticsWorkgroupMemoryMask | MemorySemanticsImageMemoryMask);
add(OCLMFEx_Image_Global,
MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask);
add(OCLMFEx_Image_Local_Global, MemorySemanticsWorkgroupMemoryMask |
MemorySemanticsCrossWorkgroupMemoryMask |
MemorySemanticsImageMemoryMask);
}

template <>
inline void SPIRVMap<OCLMemOrderKind, unsigned, MemorySemanticsMask>::init() {
add(OCLMO_relaxed, MemorySemanticsMaskNone);
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/SPIRVInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ const static char TranslateOCLMemOrder[] = "__translate_ocl_memory_order";
const static char TranslateOCLMemScope[] = "__translate_ocl_memory_scope";
const static char TranslateSPIRVMemOrder[] = "__translate_spirv_memory_order";
const static char TranslateSPIRVMemScope[] = "__translate_spirv_memory_scope";
const static char TranslateSPIRVMemFence[] = "__translate_spirv_memory_fence";
} // namespace kSPIRVName

namespace kSPIRVPostfix {
Expand Down
46 changes: 34 additions & 12 deletions lib/SPIRV/SPIRVToOCL12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,23 @@ void SPIRVToOCL12::visitCallSPIRVMemoryBarrier(CallInst *CI) {
mutateCallInstOCL(
M, CI,
[=](CallInst *, std::vector<Value *> &Args) {
auto GetArg = [=](unsigned I) {
return cast<ConstantInt>(Args[I])->getZExtValue();
};
auto Sema = mapSPIRVMemSemanticToOCL(GetArg(1));
Args.resize(1);
Args[0] = getInt32(M, Sema.first);
if (auto Arg = dyn_cast<ConstantInt>(Args[1])) {
auto Sema = mapSPIRVMemSemanticToOCL(Arg->getZExtValue());
Args.resize(1);
Args[0] = getInt32(M, Sema.first);
} else {
CallInst *TransCall = dyn_cast<CallInst>(Args[1]);
Function *F = TransCall ? TransCall->getCalledFunction() : nullptr;
if (F && F->getName().equals(kSPIRVName::TranslateOCLMemScope)) {
Args[0] = TransCall->getArgOperand(0);
} else {
Args[0] = getOrCreateSwitchFunc(kSPIRVName::TranslateSPIRVMemFence,
Args[1],
OCLMemFenceExtendedMap::getRMap(),
true /*IsReverse*/, None, CI, M);
}
Args.resize(1);
}
return kOCLBuiltinName::MemFence;
},
&Attrs);
Expand All @@ -141,12 +152,23 @@ void SPIRVToOCL12::visitCallSPIRVControlBarrier(CallInst *CI) {
mutateCallInstOCL(
M, CI,
[=](CallInst *, std::vector<Value *> &Args) {
auto GetArg = [=](unsigned I) {
return cast<ConstantInt>(Args[I])->getZExtValue();
};
auto Sema = mapSPIRVMemSemanticToOCL(GetArg(2));
Args.resize(1);
Args[0] = getInt32(M, Sema.first);
if (auto Arg = dyn_cast<ConstantInt>(Args[2])) {
auto Sema = mapSPIRVMemSemanticToOCL(Arg->getZExtValue());
Args.resize(1);
Args[0] = getInt32(M, Sema.first);
} else {
CallInst *TransCall = dyn_cast<CallInst>(Args[2]);
Function *F = TransCall ? TransCall->getCalledFunction() : nullptr;
if (F && F->getName().equals(kSPIRVName::TranslateOCLMemScope)) {
Args[0] = TransCall->getArgOperand(0);
} else {
Args[0] = getOrCreateSwitchFunc(kSPIRVName::TranslateSPIRVMemFence,
Args[2],
OCLMemFenceExtendedMap::getRMap(),
true /*IsReverse*/, None, CI, M);
}
Args.resize(1);
}
return kOCLBuiltinName::Barrier;
},
&Attrs);
Expand Down
62 changes: 62 additions & 0 deletions test/barrier_explicit_arguments.spt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
119734787 65536 393230 10 0
2 Capability Addresses
2 Capability Linkage
2 Capability Kernel
5 ExtInstImport 1 "OpenCL.std"
3 MemoryModel 1 2
3 Source 3 102000
4 Name 5 "test"
3 Name 6 "val"
4 Name 7 "entry"
6 Decorate 5 LinkageAttributes "test" Export
4 TypeInt 3 32 0
4 Constant 3 8 2
2 TypeVoid 2
4 TypeFunction 4 2 3

5 Function 2 5 0 4
3 FunctionParameter 3 6

2 Label 7
4 ControlBarrier 8 8 6
1 Return

1 FunctionEnd

; RUN: llvm-spirv %s -to-binary -o %t.spv
; RUN: spirv-val %t.spv
; RUN: llvm-spirv -r %t.spv -o %t.bc
; RUN: llvm-dis < %t.bc | FileCheck %s

; CHECK: define spir_func void @test(i32 %val)
; CHECK: %call = call spir_func i32 @__translate_spirv_memory_fence(i32 %val)
; CHECK: call spir_func void @_Z7barrierj(i32 %call)
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key)
; CHECK: entry:
; CHECK: switch i32 %key, label %default [
; CHECK: i32 256, label %case.256
; CHECK: i32 512, label %case.512
; CHECK: i32 768, label %case.768
; CHECK: i32 2048, label %case.2048
; CHECK: i32 2304, label %case.2304
; CHECK: i32 2560, label %case.2560
; CHECK: i32 2816, label %case.2816
; CHECK: ]
; CHECK: default:
; CHECK: unreachable
; CHECK: case.256:
; CHECK: ret i32 1
; CHECK: case.512:
; CHECK: ret i32 2
; CHECK: case.768:
; CHECK: ret i32 3
; CHECK: case.2048:
; CHECK: ret i32 4
; CHECK: case.2304:
; CHECK: ret i32 5
; CHECK: case.2560:
; CHECK: ret i32 6
; CHECK: case.2816:
; CHECK: ret i32 7
; CHECK: }
; CHECK: declare spir_func void @_Z7barrierj(i32)
62 changes: 62 additions & 0 deletions test/mem_fence_explicit_arguments.spt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
119734787 65536 393230 10 0
2 Capability Addresses
2 Capability Linkage
2 Capability Kernel
5 ExtInstImport 1 "OpenCL.std"
3 MemoryModel 1 2
3 Source 3 102000
4 Name 5 "test"
3 Name 6 "val"
4 Name 7 "entry"
6 Decorate 5 LinkageAttributes "test" Export
4 TypeInt 3 32 0
4 Constant 3 8 2
2 TypeVoid 2
4 TypeFunction 4 2 3

5 Function 2 5 0 4
3 FunctionParameter 3 6

2 Label 7
3 MemoryBarrier 8 6
1 Return

1 FunctionEnd

; RUN: llvm-spirv %s -to-binary -o %t.spv
; RUN: spirv-val %t.spv
; RUN: llvm-spirv -r %t.spv -o %t.bc
; RUN: llvm-dis < %t.bc | FileCheck %s

; CHECK: define spir_func void @test(i32 %val)
; CHECK: %call = call spir_func i32 @__translate_spirv_memory_fence(i32 %val)
; CHECK: call spir_func void @_Z9mem_fencej(i32 %call)
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key)
; CHECK: entry:
; CHECK: switch i32 %key, label %default [
; CHECK: i32 256, label %case.256
; CHECK: i32 512, label %case.512
; CHECK: i32 768, label %case.768
; CHECK: i32 2048, label %case.2048
; CHECK: i32 2304, label %case.2304
; CHECK: i32 2560, label %case.2560
; CHECK: i32 2816, label %case.2816
; CHECK: ]
; CHECK: default:
; CHECK: unreachable
; CHECK: case.256:
; CHECK: ret i32 1
; CHECK: case.512:
; CHECK: ret i32 2
; CHECK: case.768:
; CHECK: ret i32 3
; CHECK: case.2048:
; CHECK: ret i32 4
; CHECK: case.2304:
; CHECK: ret i32 5
; CHECK: case.2560:
; CHECK: ret i32 6
; CHECK: case.2816:
; CHECK: ret i32 7
; CHECK: }
; CHECK: declare spir_func void @_Z9mem_fencej(i32)

0 comments on commit 7a53bfb

Please sign in to comment.