Commit 4d1f8d05 by Ben Clayton

Reactor: Hook up atomic load/store intrinsics.

These may be required with the new SIMD::Load and SIMD::Store implementations. Bug b/127472316 Test: dEQP-VK.spirv_assembly.instruction.compute.opatomic.load Test: dEQP-VK.spirv_assembly.instruction.compute.opatomic.store Change-Id: I89db49d7c27c268d37d1bb768adfefd99c11c7c0 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29449 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 3c830834
...@@ -432,6 +432,54 @@ namespace rr ...@@ -432,6 +432,54 @@ namespace rr
true, // CallSupported true, // CallSupported
}; };
static std::memory_order atomicOrdering(llvm::AtomicOrdering memoryOrder)
{
switch(memoryOrder)
{
case llvm::AtomicOrdering::Monotonic: return std::memory_order_relaxed; // https://llvm.org/docs/Atomics.html#monotonic
case llvm::AtomicOrdering::Acquire: return std::memory_order_acquire;
case llvm::AtomicOrdering::Release: return std::memory_order_release;
case llvm::AtomicOrdering::AcquireRelease: return std::memory_order_acq_rel;
case llvm::AtomicOrdering::SequentiallyConsistent: return std::memory_order_seq_cst;
default:
UNREACHABLE("memoryOrder: %d", memoryOrder);
return std::memory_order_acq_rel;
}
}
static llvm::AtomicOrdering atomicOrdering(bool atomic, std::memory_order memoryOrder)
{
if(!atomic)
{
return llvm::AtomicOrdering::NotAtomic;
}
switch(memoryOrder)
{
case std::memory_order_relaxed: return llvm::AtomicOrdering::Monotonic; // https://llvm.org/docs/Atomics.html#monotonic
case std::memory_order_consume: return llvm::AtomicOrdering::Acquire; // https://llvm.org/docs/Atomics.html#acquire: "It should also be used for C++11/C11 memory_order_consume."
case std::memory_order_acquire: return llvm::AtomicOrdering::Acquire;
case std::memory_order_release: return llvm::AtomicOrdering::Release;
case std::memory_order_acq_rel: return llvm::AtomicOrdering::AcquireRelease;
case std::memory_order_seq_cst: return llvm::AtomicOrdering::SequentiallyConsistent;
default:
UNREACHABLE("memoryOrder: %d", int(memoryOrder));
return llvm::AtomicOrdering::AcquireRelease;
}
}
template <typename T>
static void atomicLoad(void *ptr, void *ret, llvm::AtomicOrdering ordering)
{
*reinterpret_cast<T*>(ret) = std::atomic_load_explicit<T>(reinterpret_cast<std::atomic<T>*>(ptr), atomicOrdering(ordering));
}
template <typename T>
static void atomicStore(void *ptr, void *val, llvm::AtomicOrdering ordering)
{
std::atomic_store_explicit<T>(reinterpret_cast<std::atomic<T>*>(ptr), *reinterpret_cast<T*>(val), atomicOrdering(ordering));
}
class ExternalFunctionSymbolResolver class ExternalFunctionSymbolResolver
{ {
private: private:
...@@ -441,9 +489,36 @@ namespace rr ...@@ -441,9 +489,36 @@ namespace rr
public: public:
ExternalFunctionSymbolResolver() ExternalFunctionSymbolResolver()
{ {
struct Atomic
{
static void load(size_t size, void *ptr, void *ret, llvm::AtomicOrdering ordering)
{
switch (size)
{
case 1: atomicLoad<uint8_t>(ptr, ret, ordering); break;
case 2: atomicLoad<uint16_t>(ptr, ret, ordering); break;
case 4: atomicLoad<uint32_t>(ptr, ret, ordering); break;
case 8: atomicLoad<uint64_t>(ptr, ret, ordering); break;
default:
UNIMPLEMENTED("Atomic::load(size: %d)", int(size));
}
}
static void store(size_t size, void *ptr, void *ret, llvm::AtomicOrdering ordering)
{
switch (size)
{
case 1: atomicStore<uint8_t>(ptr, ret, ordering); break;
case 2: atomicStore<uint16_t>(ptr, ret, ordering); break;
case 4: atomicStore<uint32_t>(ptr, ret, ordering); break;
case 8: atomicStore<uint64_t>(ptr, ret, ordering); break;
default:
UNIMPLEMENTED("Atomic::store(size: %d)", int(size));
}
}
};
struct F { static void nop() {} }; struct F { static void nop() {} };
func_.emplace("nop", reinterpret_cast<void*>(F::nop));
func_.emplace("nop", reinterpret_cast<void*>(F::nop));
func_.emplace("floorf", reinterpret_cast<void*>(floorf)); func_.emplace("floorf", reinterpret_cast<void*>(floorf));
func_.emplace("nearbyintf", reinterpret_cast<void*>(nearbyintf)); func_.emplace("nearbyintf", reinterpret_cast<void*>(nearbyintf));
func_.emplace("truncf", reinterpret_cast<void*>(truncf)); func_.emplace("truncf", reinterpret_cast<void*>(truncf));
...@@ -467,9 +542,10 @@ namespace rr ...@@ -467,9 +542,10 @@ namespace rr
func_.emplace("logf", reinterpret_cast<void*>(logf)); func_.emplace("logf", reinterpret_cast<void*>(logf));
func_.emplace("exp2f", reinterpret_cast<void*>(exp2f)); func_.emplace("exp2f", reinterpret_cast<void*>(exp2f));
func_.emplace("log2f", reinterpret_cast<void*>(log2f)); func_.emplace("log2f", reinterpret_cast<void*>(log2f));
func_.emplace("atomic_load", reinterpret_cast<void*>(Atomic::load));
func_.emplace("atomic_store", reinterpret_cast<void*>(Atomic::store));
#ifdef __APPLE__ #ifdef __APPLE__
// LLVM uses this function on macOS for tan.
func_.emplace("sincosf_stret", reinterpret_cast<void*>(__sincosf_stret)); func_.emplace("sincosf_stret", reinterpret_cast<void*>(__sincosf_stret));
#elif defined(__linux__) #elif defined(__linux__)
func_.emplace("sincosf", reinterpret_cast<void*>(sincosf)); func_.emplace("sincosf", reinterpret_cast<void*>(sincosf));
...@@ -775,27 +851,6 @@ namespace rr ...@@ -775,27 +851,6 @@ namespace rr
} }
} }
static llvm::AtomicOrdering atomicOrdering(bool atomic, std::memory_order memoryOrder)
{
if(!atomic)
{
return llvm::AtomicOrdering::NotAtomic;
}
switch(memoryOrder)
{
case std::memory_order_relaxed: return llvm::AtomicOrdering::Monotonic; // https://llvm.org/docs/Atomics.html#monotonic
case std::memory_order_consume: return llvm::AtomicOrdering::Acquire; // https://llvm.org/docs/Atomics.html#acquire: "It should also be used for C++11/C11 memory_order_consume."
case std::memory_order_acquire: return llvm::AtomicOrdering::Acquire;
case std::memory_order_release: return llvm::AtomicOrdering::Release;
case std::memory_order_acq_rel: return llvm::AtomicOrdering::AcquireRelease;
case std::memory_order_seq_cst: return llvm::AtomicOrdering::SequentiallyConsistent;
default:
UNREACHABLE("memoryOrder: %d", int(memoryOrder));
return llvm::AtomicOrdering::AcquireRelease;
}
}
Nucleus::Nucleus() Nucleus::Nucleus()
{ {
::codegenMutex.lock(); // Reactor and LLVM are currently not thread safe ::codegenMutex.lock(); // Reactor and LLVM are currently not thread safe
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment