SpirvShader: Implement OpMemoryBarrier.
Tests: dEQP-VK.spirv_assembly.instruction.compute.workgroup_memory.*
Tests: dEQP-VK.subgroups.basic.compute.*
Tests: dEQP-VK.compute.basic.*
Bug: b/132232716
Change-Id: If238f6b4af5c0ff6909a62241e0adb5677cb6c0b
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30852
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index ecb74f3..8616bea 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -1455,6 +1455,11 @@
::builder->CreateCall(func, { V(val), elPtrs, align, i8Mask });
}
+ void Nucleus::createFence(std::memory_order memoryOrder)
+ {
+ ::builder->CreateFence(atomicOrdering(true, memoryOrder));
+ }
+
Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
{
RR_DEBUG_INFO_UPDATE_LOC();
diff --git a/src/Reactor/Nucleus.hpp b/src/Reactor/Nucleus.hpp
index 59ece44..a27c4e9 100644
--- a/src/Reactor/Nucleus.hpp
+++ b/src/Reactor/Nucleus.hpp
@@ -124,6 +124,9 @@
static Value *createGather(Value *base, Type *elementType, Value *offsets, Value *mask, unsigned int alignment);
static void createScatter(Value *base, Value *value, Value *offsets, Value *mask, unsigned int alignment);
+ // Barrier instructions
+ static void createFence(std::memory_order memoryOrder);
+
// Atomic instructions
static Value *createAtomicAdd(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed);
static Value *createAtomicSub(Value *ptr, Value *value, std::memory_order memoryOrder = std::memory_order_relaxed);
diff --git a/src/Reactor/Reactor.cpp b/src/Reactor/Reactor.cpp
index 56ab1da..c4740a7 100644
--- a/src/Reactor/Reactor.cpp
+++ b/src/Reactor/Reactor.cpp
@@ -13,6 +13,7 @@
// limitations under the License.
#include "Reactor.hpp"
+#include "Debug.hpp"
// Define REACTOR_MATERIALIZE_LVALUES_ON_DEFINITION to non-zero to ensure all
// variables have a stack location obtained throuch alloca().
@@ -4226,4 +4227,14 @@
Nucleus::createScatter(base.value, val.value, offsets.value, mask.value, alignment);
}
+ void Fence(std::memory_order memoryOrder)
+ {
+ ASSERT_MSG(memoryOrder == std::memory_order_acquire ||
+ memoryOrder == std::memory_order_release ||
+ memoryOrder == std::memory_order_acq_rel ||
+ memoryOrder == std::memory_order_seq_cst,
+ "Unsupported memoryOrder: %d", int(memoryOrder));
+ Nucleus::createFence(memoryOrder);
+ }
+
}
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 38bc625..6fbc061 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -2385,6 +2385,11 @@
Store(RValue<T>(value), RValue<Pointer<T>>(pointer), alignment, atomic, memoryOrder);
}
+ // Fence adds a memory barrier that enforces ordering constraints on memory
+ // operations. memoryOrder can only be one of:
+ // std::memory_order_acquire, std::memory_order_release,
+ // std::memory_order_acq_rel, or std::memory_order_seq_cst.
+ void Fence(std::memory_order memoryOrder);
template<class T, int S = 1>
class Array : public LValue<T>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index e196415..4310aba 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -3455,6 +3455,7 @@
// Below are functions currently unimplemented for the Subzero backend.
// They are stubbed to satisfy the linker.
+ void Nucleus::createFence(std::memory_order memoryOrder) { UNIMPLEMENTED("Subzero createFence()"); }
Value *Nucleus::createGather(Value *base, Type *elTy, Value *offsets, Value *mask, unsigned int alignment) { UNIMPLEMENTED("Subzero createGather()"); return nullptr; }
void Nucleus::createScatter(Value *base, Value *val, Value *offsets, Value *mask, unsigned int alignment) { UNIMPLEMENTED("Subzero createScatter()"); }
RValue<Float4> Sin(RValue<Float4> x) { UNIMPLEMENTED("Subzero Sin()"); return Float4(0); }