[llvm] [SPIR-V] Honor explicit memory_order/memory_scope in atomic load/store (PR #215572)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 07:05:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Arseniy Obolenskiy (aobolensk)
<details>
<summary>Changes</summary>
atomic_load_explicit and atomic_store_explicit ignored their memory_order/memory_scope arguments
Translate the explicit arguments via the existing buildMemSemanticsReg/buildScopeReg helpers, as buildAtomicRMWInst already does
---
Full diff: https://github.com/llvm/llvm-project/pull/215572.diff
2 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+24-20)
- (modified) llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll (+12-3)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 89b0292bc656b..38c770aed5836 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -635,24 +635,22 @@ static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call,
if (Call->isSpirvOp())
return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicLoad, Call, TypeReg);
+ // atomic_load_explicit(ptr, memory_order[, memory_scope]).
Register PtrRegister = Call->Arguments[0];
- // TODO: if true insert call to __translate_ocl_memory_sccope before
- // OpAtomicLoad and the function implementation. We can use Translator's
- // output for transcoding/atomic_explicit_arguments.cl as an example.
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+
+ unsigned Semantics =
+ SPIRV::MemorySemantics::SequentiallyConsistent |
+ getMemSemanticsForStorageClass(GR->getPointerStorageClass(PtrRegister));
+ Register MemSemanticsReg =
+ Call->Arguments.size() >= 2 ? Call->Arguments[1] : Register();
+ MemSemanticsReg = buildMemSemanticsReg(MemSemanticsReg, PtrRegister,
+ Semantics, MIRBuilder, GR);
+
Register ScopeRegister =
- Call->Arguments.size() > 1
- ? Call->Arguments[1]
- : buildConstantIntReg32(SPIRV::Scope::Device, MIRBuilder, GR);
- Register MemSemanticsReg;
- if (Call->Arguments.size() > 2) {
- // TODO: Insert call to __translate_ocl_memory_order before OpAtomicLoad.
- MemSemanticsReg = Call->Arguments[2];
- } else {
- int Semantics =
- SPIRV::MemorySemantics::SequentiallyConsistent |
- getMemSemanticsForStorageClass(GR->getPointerStorageClass(PtrRegister));
- MemSemanticsReg = buildConstantIntReg32(Semantics, MIRBuilder, GR);
- }
+ Call->Arguments.size() >= 3 ? Call->Arguments[2] : Register();
+ ScopeRegister =
+ buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
MIRBuilder.buildInstr(SPIRV::OpAtomicLoad)
.addDef(Call->ReturnRegister)
@@ -671,13 +669,19 @@ static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call,
return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicStore, Call,
Register(0));
- Register ScopeRegister =
- buildConstantIntReg32(SPIRV::Scope::Device, MIRBuilder, GR);
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
Register PtrRegister = Call->Arguments[0];
- int Semantics =
+ unsigned Semantics =
SPIRV::MemorySemantics::SequentiallyConsistent |
getMemSemanticsForStorageClass(GR->getPointerStorageClass(PtrRegister));
- Register MemSemanticsReg = buildConstantIntReg32(Semantics, MIRBuilder, GR);
+ Register MemSemanticsReg =
+ Call->Arguments.size() >= 3 ? Call->Arguments[2] : Register();
+ MemSemanticsReg = buildMemSemanticsReg(MemSemanticsReg, PtrRegister,
+ Semantics, MIRBuilder, GR);
+ Register ScopeRegister =
+ Call->Arguments.size() >= 4 ? Call->Arguments[3] : Register();
+ ScopeRegister =
+ buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
MIRBuilder.buildInstr(SPIRV::OpAtomicStore)
.addUse(PtrRegister)
.addUse(ScopeRegister)
diff --git a/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll b/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll
index cb81df5b61019..4c41fe3c92694 100644
--- a/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll
+++ b/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll
@@ -3,12 +3,21 @@
;; Types:
; CHECK: %[[#F32:]] = OpTypeFloat 32
+; CHECK: %[[#I32:]] = OpTypeInt 32 0
;; Constants:
-; CHECK: %[[#CONST:]] = OpConstant %[[#F32]] 1
+; CHECK-DAG: %[[#CONST:]] = OpConstant %[[#F32]] 1
+; CHECK-DAG: %[[#RELAXED:]] = OpConstantNull %[[#I32]]
+; CHECK-DAG: %[[#DEVICE:]] = OpConstant %[[#I32]] 1
+; CHECK-DAG: %[[#WORKGROUP:]] = OpConstant %[[#I32]] 2
+; CHECK-DAG: %[[#SEQCST:]] = OpConstant %[[#I32]] 16
;; Atomic instructions:
; CHECK: OpStore %[[#]] %[[#CONST]]
-; CHECK-COUNT-3: OpAtomicStore
-; CHECK-COUNT-3: OpAtomicLoad
+; CHECK: OpAtomicStore %[[#]] %[[#DEVICE]] %[[#SEQCST]] %[[#CONST]]
+; CHECK: OpAtomicStore %[[#]] %[[#DEVICE]] %[[#RELAXED]] %[[#CONST]]
+; CHECK: OpAtomicStore %[[#]] %[[#WORKGROUP]] %[[#RELAXED]] %[[#CONST]]
+; CHECK: OpAtomicLoad %[[#]] %[[#]] %[[#DEVICE]] %[[#SEQCST]]
+; CHECK: OpAtomicLoad %[[#]] %[[#]] %[[#DEVICE]] %[[#RELAXED]]
+; CHECK: OpAtomicLoad %[[#]] %[[#]] %[[#WORKGROUP]] %[[#RELAXED]]
; CHECK-COUNT-3: OpAtomicExchange
define spir_kernel void @test_atomic_kernel(ptr addrspace(3) %ff) local_unnamed_addr #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/215572
More information about the llvm-commits
mailing list