Add support for OpAtomicCompareExchange

Includes associated Reactor plumbing.

Bug: b/130768731
Bug: b/127472316
Test: dEQP-VK.image.*
Change-Id: I700eb29f976410b59778e4ed162066b84a55a974
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29456
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 9bfc908..c196880 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -1493,6 +1493,15 @@
 		return V(::builder->CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, V(ptr), V(value), atomicOrdering(true, memoryOrder)));
 	}
 
+	Value *Nucleus::createAtomicCompareExchange(Value *ptr, Value *value, Value *compare, std::memory_order memoryOrderEqual, std::memory_order memoryOrderUnequal)
+	{
+		RR_DEBUG_INFO_UPDATE_LOC();
+		// Note: AtomicCmpXchgInstruction returns a 1-member struct containing the result, not the result directly.
+		return V(::builder->CreateExtractValue(
+				::builder->CreateAtomicCmpXchg(V(ptr), V(compare), V(value), atomicOrdering(true, memoryOrderEqual), atomicOrdering(true, memoryOrderUnequal)),
+				llvm::ArrayRef<unsigned>(0u)));
+	}
+
 	Value *Nucleus::createTrunc(Value *v, Type *destType)
 	{
 		RR_DEBUG_INFO_UPDATE_LOC();