[llvm] 77cc884 - [SPIRV] Preserve FP types in atomic load/store instead of casting to integer (#194583)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 3 08:59:21 PDT 2026


Author: Viktoria Maximova
Date: 2026-07-03T17:59:16+02:00
New Revision: 77cc8841df4f1ced13ff16e7338b0f5625ad3850

URL: https://github.com/llvm/llvm-project/commit/77cc8841df4f1ced13ff16e7338b0f5625ad3850
DIFF: https://github.com/llvm/llvm-project/commit/77cc8841df4f1ced13ff16e7338b0f5625ad3850.diff

LOG: [SPIRV] Preserve FP types in atomic load/store instead of casting to integer (#194583)

The default
`TargetLowering::shouldCastAtomicLoadInIR`/`shouldCastAtomicStoreInIR`
cast all FP atomics to integer, producing unnecessary bitcasts in SPIR-V
output. Override both to return None, matching the existing
`shouldCastAtomicRMWIInIR` behavior and letting
`OpAtomicLoad`/`OpAtomicStore` operate on FP types directly.

Also updated 16-bit atomics tests from #184312 to use native load/store
atomic instructions now that the SPIRV backend supports them (landed in
#185696).

AI-assisted: Claude Sonnet 4.6 (commercial SaaS)

Added: 
    

Modified: 
    llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
    llvm/lib/Target/SPIRV/SPIRVISelLowering.h
    llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll
    llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll
    llvm/test/CodeGen/SPIRV/transcoding/load-atomic.ll
    llvm/test/CodeGen/SPIRV/transcoding/store-atomic.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index eb16c9a314a23..ba881c7a61616 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -684,3 +684,18 @@ SPIRVTargetLowering::shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const {
   // SPIR-V only supports atomic exchange for integer and floating-point types.
   return AtomicExpansionKind::None;
 }
+
+TargetLowering::AtomicExpansionKind
+SPIRVTargetLowering::shouldCastAtomicLoadInIR(LoadInst *LI) const {
+  // TODO: pointer load should return CastToInteger, but
+  // convertAtomicLoadToIntegerType uses BitCast which asserts on pointer types.
+  return AtomicExpansionKind::None;
+}
+
+TargetLowering::AtomicExpansionKind
+SPIRVTargetLowering::shouldCastAtomicStoreInIR(StoreInst *SI) const {
+  // TODO: pointer store should return CastToInteger, but
+  // convertAtomicStoreToIntegerType uses BitCast which asserts on pointer
+  // types.
+  return AtomicExpansionKind::None;
+}

diff  --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
index 6af0bbcc9818d..c86e37b2b2528 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
@@ -78,6 +78,8 @@ class SPIRVTargetLowering : public TargetLowering {
   shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const override;
   AtomicExpansionKind
   shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const override;
+  AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override;
+  AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override;
 
   bool shouldIssueAtomicLoadForAtomicEmulationLoop() const override {
     return false;

diff  --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll
index edd3c64ecb3a0..ff34aa00d2c45 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll
@@ -14,14 +14,13 @@
 ; CHECK-DAG: %[[#TyInt32:]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[#Const42:]] = OpConstant %[[#TyBF16]] 16936{{$}}
 ; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyBF16]]
-; CHECK-DAG: %[[#ScopeDevice:]] = OpConstant %[[#TyInt32]] 1{{$}}
 ; CHECK-DAG: %[[#ScopeAllSvmDevices:]] = OpConstantNull %[[#TyInt32]]
 ; CHECK-DAG: %[[#MemSem528:]] = OpConstant %[[#TyInt32]] 528{{$}}
 
 ; CHECK-DAG: %[[#Val:]] = OpVariable %[[#TyBF16Ptr]] CrossWorkgroup %[[#Const0]]
 
-; CHECK: OpAtomicLoad %[[#TyBF16]] %[[#Val]] %[[#ScopeDevice]] %[[#MemSem528]]
-; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeDevice]] %[[#MemSem528]] %[[#Const42]]
+; CHECK: OpAtomicLoad %[[#TyBF16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]]
+; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]] %[[#Const42]]
 ; CHECK: OpAtomicExchange %[[#TyBF16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]] %[[#Const42]]
 
 
@@ -29,14 +28,8 @@
 
 define spir_func void @test_atomic_bfloat16_load_store_xchg() {
 entry:
-; TODO: 'load atomic'/'store atomic' LLVM instructions are not yet lowered to
-; OpAtomicLoad/OpAtomicStore by the SPIRV backend; use OCL builtins instead.
-; TODO: test Vulkan path as well once we support atomic load/store.
-  %load = call spir_func bfloat @_Z11atomic_loadPU3AS1VU7_AtomicDF16b(ptr addrspace(1) @val)
-  call spir_func void @_Z12atomic_storePU3AS1VU7_AtomicDF16bDF16b(ptr addrspace(1) @val, bfloat 42.000000e+00)
+  %load = load atomic bfloat, ptr addrspace(1) @val seq_cst, align 2
+  store atomic bfloat 42.000000e+00, ptr addrspace(1) @val seq_cst, align 2
   %xchg = atomicrmw xchg ptr addrspace(1) @val, bfloat 42.000000e+00 seq_cst
   ret void
 }
-
-declare spir_func bfloat @_Z11atomic_loadPU3AS1VU7_AtomicDF16b(ptr addrspace(1))
-declare spir_func void @_Z12atomic_storePU3AS1VU7_AtomicDF16bDF16b(ptr addrspace(1), bfloat)

diff  --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll
index 8d74032b4d66a..ebade9c2fbd9e 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll
@@ -15,14 +15,13 @@
 ; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyInt16]]
 ; CHECK-DAG: %[[#Const1:]] = OpConstant %[[#TyInt16]] 1{{$}}
 ; CHECK-DAG: %[[#Const42:]] = OpConstant %[[#TyInt16]] 42{{$}}
-; CHECK-DAG: %[[#ScopeDevice:]] = OpConstant %[[#TyInt32]] 1{{$}}
 ; CHECK-DAG: %[[#ScopeAllSvmDevices:]] = OpConstantNull %[[#TyInt32]]
 ; CHECK-DAG: %[[#MemSem528:]] = OpConstant %[[#TyInt32]] 528{{$}}
 
 ; CHECK-DAG: %[[#Val:]] = OpVariable %[[#TyInt16Ptr]] CrossWorkgroup %[[#Const0]]
 
-; CHECK: OpAtomicLoad %[[#TyInt16]] %[[#Val]] %[[#ScopeDevice]] %[[#MemSem528]]
-; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeDevice]] %[[#MemSem528]] %[[#Const42]]
+; CHECK: OpAtomicLoad %[[#TyInt16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]]
+; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]] %[[#Const42]]
 ; CHECK: OpAtomicExchange %[[#TyInt16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]] %[[#Const42]]
 ; CHECK: OpAtomicCompareExchange %[[#TyInt16]] %[[#]] %[[#ScopeAllSvmDevices]] %[[#MemSem528]] %[[#MemSem528]] %[[#Const42]] %[[#Const1]]
 
@@ -31,14 +30,9 @@
 
 define spir_func void @test_atomic_int16_basic() {
 entry:
-; TODO: 'load atomic'/'store atomic' LLVM instructions are not yet lowered to
-; OpAtomicLoad/OpAtomicStore by the SPIRV backend; use OCL builtins instead.
-  %load = call spir_func i16 @_Z11atomic_loadPU3AS1VU7_Atomics(ptr addrspace(1) @val)
-  call spir_func void @_Z12atomic_storePU3AS1VU7_Atomicss(ptr addrspace(1) @val, i16 42)
+  %load = load atomic i16, ptr addrspace(1) @val seq_cst, align 2
+  store atomic i16 42, ptr addrspace(1) @val seq_cst, align 2
   %xchg = atomicrmw xchg ptr addrspace(1) @val, i16 42 seq_cst
   %cmpxchg = cmpxchg ptr addrspace(1) @val, i16 1, i16 42 seq_cst seq_cst
   ret void
 }
-
-declare spir_func i16 @_Z11atomic_loadPU3AS1VU7_Atomics(ptr addrspace(1))
-declare spir_func void @_Z12atomic_storePU3AS1VU7_Atomicss(ptr addrspace(1), i16)

diff  --git a/llvm/test/CodeGen/SPIRV/transcoding/load-atomic.ll b/llvm/test/CodeGen/SPIRV/transcoding/load-atomic.ll
index d04e17ae79635..29cba25cc6cb4 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/load-atomic.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/load-atomic.ll
@@ -101,8 +101,7 @@ define i32 @load_i32_acquire_device(ptr addrspace(1) %ptr) {
 define float @load_float_acquire(ptr addrspace(1) %ptr) {
 ; CHECK-LABEL: OpFunction %[[#]]
 ; CHECK:       %[[#ptr:]] = OpFunctionParameter %[[#]]
-; CHECK:       %[[#load:]] = OpAtomicLoad %[[#Int32]] %[[#ptr]] %[[#Const0]] %[[#Const514]]
-; CHECK:       %[[#val:]] = OpBitcast %[[#Float]] %[[#load]]
+; CHECK:       %[[#val:]] = OpAtomicLoad %[[#Float]] %[[#ptr]] %[[#Const0]] %[[#Const514]]
 ; CHECK:       OpReturnValue %[[#val]]
   %val = load atomic float, ptr addrspace(1) %ptr acquire, align 8
   ret float %val

diff  --git a/llvm/test/CodeGen/SPIRV/transcoding/store-atomic.ll b/llvm/test/CodeGen/SPIRV/transcoding/store-atomic.ll
index 2830b212bd089..5e81f207e09f5 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/store-atomic.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/store-atomic.ll
@@ -110,8 +110,7 @@ define void @store_float_release(ptr addrspace(1) %ptr, float %val) {
 ; CHECK-LABEL: OpFunction %[[#]]
 ; CHECK:       %[[#ptr:]] = OpFunctionParameter %[[#]]
 ; CHECK:       %[[#val:]] = OpFunctionParameter %[[#Float]]
-; CHECK:       %[[#cast:]] = OpBitcast %[[#Int32]] %[[#val]]
-; CHECK:       OpAtomicStore %[[#ptr]] %[[#Const0]] %[[#Const516]] %[[#cast]]
+; CHECK:       OpAtomicStore %[[#ptr]] %[[#Const0]] %[[#Const516]] %[[#val]]
 ; CHECK:       OpReturn
   store atomic float %val, ptr addrspace(1) %ptr release, align 8
   ret void


        


More information about the llvm-commits mailing list