From 9704b35663db346c081ac02032cb4ab669a2a0f1 Mon Sep 17 00:00:00 2001 From: Alexey Sachkov Date: Tue, 12 May 2020 17:12:24 +0300 Subject: [PATCH] Improve handling of OpMemoryBarrier Added support for non-constant 'Semantics' operand --- llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp | 33 +++++++++++-------- .../test/mem_fence_explicit_arguments.spt | 32 ++++++++++++++++-- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp b/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp index 6686d886e50f4..86eae4bcbd6b6 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp @@ -107,20 +107,25 @@ bool SPIRVToOCL20::runOnModule(Module &Module) { void SPIRVToOCL20::visitCallSPIRVMemoryBarrier(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); - mutateCallInstOCL(M, CI, - [=](CallInst *, std::vector &Args) { - auto GetArg = [=](unsigned I) { - return cast(Args[I])->getZExtValue(); - }; - auto MScope = static_cast(GetArg(0)); - auto Sema = mapSPIRVMemSemanticToOCL(GetArg(1)); - Args.resize(3); - Args[0] = getInt32(M, Sema.first); - Args[1] = getInt32(M, Sema.second); - Args[2] = getInt32(M, rmap(MScope)); - return kOCLBuiltinName::AtomicWorkItemFence; - }, - &Attrs); + mutateCallInstOCL( + M, CI, + [=](CallInst *, std::vector &Args) { + Value *MemScope = + getInt32(M, rmap(static_cast( + cast(Args[0])->getZExtValue()))); + Value *MemFenceFlags = + SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[1], CI); + Value *MemOrder = + SPIRV::transSPIRVMemorySemanticsIntoOCLMemoryOrder(Args[1], CI); + + Args.resize(3); + Args[0] = MemFenceFlags; + Args[1] = MemOrder; + Args[2] = MemScope; + + return kOCLBuiltinName::AtomicWorkItemFence; + }, + &Attrs); } void SPIRVToOCL20::visitCallSPIRVControlBarrier(CallInst *CI) { diff --git a/llvm-spirv/test/mem_fence_explicit_arguments.spt b/llvm-spirv/test/mem_fence_explicit_arguments.spt index 1518f7bf4b6ce..46838bcaec9fc 100644 --- a/llvm-spirv/test/mem_fence_explicit_arguments.spt +++ b/llvm-spirv/test/mem_fence_explicit_arguments.spt @@ -26,11 +26,15 @@ ; 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 +; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefixes CHECK,CHECK-12 +; RUN: llvm-spirv -r %t.spv --spirv-target-env=CL2.0 -o %t.bc +; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefixes CHECK,CHECK-20 ; 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-12: call spir_func void @_Z9mem_fencej(i32 %call) +; CHECK-20: %call1 = call spir_func i32 @__translate_spirv_memory_order(i32 %val) +; CHECK-20: call spir_func void @_Z22atomic_work_item_fencej12memory_order12memory_scope(i32 %call, i32 %call1 ; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key) ; CHECK: entry: ; CHECK: %key.masked = and i32 2816, %key @@ -60,4 +64,26 @@ ; CHECK: case.2816: ; CHECK: ret i32 7 ; CHECK: } -; CHECK: declare spir_func void @_Z9mem_fencej(i32) +; CHECK-20: define private spir_func i32 @__translate_spirv_memory_order(i32 %key) { +; CHECK-20: entry: +; CHECK-20: %key.masked = and i32 30, %key +; CHECK-20: switch i32 %key.masked, label %default [ +; CHECK-20: i32 0, label %case.0 +; CHECK-20: i32 2, label %case.2 +; CHECK-20: i32 4, label %case.4 +; CHECK-20: i32 8, label %case.8 +; CHECK-20: i32 16, label %case.16 +; CHECK-20: ] +; CHECK-20: default: +; CHECK-20: unreachable +; CHECK-20: case.0: +; CHECK-20: ret i32 0 +; CHECK-20: case.2: +; CHECK-20: ret i32 2 +; CHECK-20: case.4: +; CHECK-20: ret i32 3 +; CHECK-20: case.8: +; CHECK-20: ret i32 4 +; CHECK-20: case.16: +; CHECK-20: ret i32 5 +; CHECK-20: }