[llvm] [SPIR-V] Complete SPV_INTEL_16bit_atomics extension support (PR #184312)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 3 02:07:00 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Viktoria Maximova (vmaksimo)
<details>
<summary>Changes</summary>
Add missing capabilities to finalize SPV_INTEL_16bit_atomics extension:
- AtomicInt16CompareExchangeINTEL (6260): for i16 load/store/exchange/cmpxchg
- Int16AtomicsINTEL (6261): for i16 arithmetic atomics (add, sub, min, max, etc.)
- AtomicBFloat16LoadStoreINTEL (6262): for bfloat16 load/store/exchange
This completes the implementation started in 6ef3218.
Specification:
https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_16bit_atomics.asciidoc
---
Full diff: https://github.com/llvm/llvm-project/pull/184312.diff
5 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+34)
- (modified) llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td (+6-3)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll (+38)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_arithmetic.ll (+44)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll (+31)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 86659c623ebf2..79429f4fd10cc 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1622,10 +1622,44 @@ void addInstrRequirements(const MachineInstr &MI,
assert(InstrPtr->getOperand(1).isReg() && "Unexpected operand in atomic");
Register TypeReg = InstrPtr->getOperand(1).getReg();
SPIRVTypeInst TypeDef = MRI.getVRegDef(TypeReg);
+ unsigned Op = MI.getOpcode();
+
if (TypeDef->getOpcode() == SPIRV::OpTypeInt) {
unsigned BitWidth = TypeDef->getOperand(1).getImm();
if (BitWidth == 64)
Reqs.addCapability(SPIRV::Capability::Int64Atomics);
+ else if (BitWidth == 16) {
+ if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
+ report_fatal_error(
+ "16-bit integer atomic operations require the following SPIR-V "
+ "extension: SPV_INTEL_16bit_atomics",
+ false);
+ Reqs.addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
+ switch (Op) {
+ case SPIRV::OpAtomicLoad:
+ case SPIRV::OpAtomicStore:
+ case SPIRV::OpAtomicExchange:
+ case SPIRV::OpAtomicCompareExchange:
+ case SPIRV::OpAtomicCompareExchangeWeak:
+ Reqs.addCapability(
+ SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
+ break;
+ default:
+ Reqs.addCapability(SPIRV::Capability::Int16AtomicsINTEL);
+ break;
+ }
+ }
+ } else if (isBFloat16Type(TypeDef)) {
+ if (Op == SPIRV::OpAtomicLoad || Op == SPIRV::OpAtomicStore ||
+ Op == SPIRV::OpAtomicExchange) {
+ if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
+ report_fatal_error(
+ "The atomic bfloat16 instruction requires the following SPIR-V "
+ "extension: SPV_INTEL_16bit_atomics",
+ false);
+ Reqs.addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
+ Reqs.addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
+ }
}
break;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index a0b7a4b0b4f44..957f0188c80f3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -516,6 +516,7 @@ defm FragmentMaskAMD : CapabilityOperand<5010, 0, 0, [], [Shader]>;
defm StencilExportEXT : CapabilityOperand<5013, 0, 0, [], [Shader]>;
defm ImageReadWriteLodAMD : CapabilityOperand<5015, 0, 0, [], [Shader]>;
defm ShaderClockKHR : CapabilityOperand<5055, 0, 0, [SPV_KHR_shader_clock], []>;
+defm BFloat16TypeKHR : CapabilityOperand<5116, 0, 0, [SPV_KHR_bfloat16], []>;
defm SampleMaskOverrideCoverageNV : CapabilityOperand<5249, 0, 0, [], [SampleRateShading]>;
defm GeometryShaderPassthroughNV : CapabilityOperand<5251, 0, 0, [], [Geometry]>;
defm ShaderViewportIndexLayerEXT : CapabilityOperand<5254, 0, 0, [], [MultiViewport]>;
@@ -574,12 +575,15 @@ defm AtomicFloat32AddEXT : CapabilityOperand<6033, 0, 0, [SPV_EXT_shader_atomic_
defm AtomicFloat64AddEXT : CapabilityOperand<6034, 0, 0, [SPV_EXT_shader_atomic_float_add], []>;
defm FmaKHR : CapabilityOperand<6030, 0, 0, [SPV_KHR_fma], []>;
defm AtomicFloat16AddEXT : CapabilityOperand<6095, 0, 0, [SPV_EXT_shader_atomic_float16_add], []>;
-defm AtomicBFloat16AddINTEL : CapabilityOperand<6255, 0, 0, [SPV_INTEL_16bit_atomics], []>;
+defm AtomicBFloat16AddINTEL : CapabilityOperand<6255, 0, 0, [SPV_INTEL_16bit_atomics], [BFloat16TypeKHR]>;
defm AtomicFloat16MinMaxEXT : CapabilityOperand<5616, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>;
defm AtomicFloat32MinMaxEXT : CapabilityOperand<5612, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>;
defm AtomicFloat64MinMaxEXT : CapabilityOperand<5613, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>;
-defm AtomicBFloat16MinMaxINTEL : CapabilityOperand<6256, 0, 0, [SPV_INTEL_16bit_atomics], []>;
+defm AtomicBFloat16MinMaxINTEL : CapabilityOperand<6256, 0, 0, [SPV_INTEL_16bit_atomics], [BFloat16TypeKHR]>;
defm AtomicFloat16VectorNV : CapabilityOperand<5404, 0, 0, [SPV_NV_shader_atomic_fp16_vector], []>;
+defm AtomicInt16CompareExchangeINTEL : CapabilityOperand<6260, 0, 0, [SPV_INTEL_16bit_atomics], [Int16]>;
+defm Int16AtomicsINTEL : CapabilityOperand<6261, 0, 0, [SPV_INTEL_16bit_atomics], [AtomicInt16CompareExchangeINTEL]>;
+defm AtomicBFloat16LoadStoreINTEL : CapabilityOperand<6262, 0, 0, [SPV_INTEL_16bit_atomics], [BFloat16TypeKHR]>;
defm VariableLengthArrayINTEL : CapabilityOperand<5817, 0, 0, [SPV_INTEL_variable_length_array], []>;
defm GroupUniformArithmeticKHR : CapabilityOperand<6400, 0, 0, [SPV_KHR_uniform_group_instructions], []>;
defm USMStorageClassesINTEL : CapabilityOperand<5935, 0, 0, [SPV_INTEL_usm_storage_classes], [Kernel]>;
@@ -619,7 +623,6 @@ defm PredicatedIOINTEL : CapabilityOperand<6257, 0, 0, [SPV_INTEL_predicated_io]
defm Int4TypeINTEL : CapabilityOperand<5112, 0, 0, [SPV_INTEL_int4], []>;
defm Int4CooperativeMatrixINTEL : CapabilityOperand<5114, 0, 0, [SPV_INTEL_int4], [Int4TypeINTEL, CooperativeMatrixKHR]>;
defm TensorFloat32RoundingINTEL : CapabilityOperand<6425, 0, 0, [SPV_INTEL_tensor_float32_conversion], []>;
-defm BFloat16TypeKHR : CapabilityOperand<5116, 0, 0, [SPV_KHR_bfloat16], []>;
defm BFloat16DotProductKHR : CapabilityOperand<5117, 0, 0, [SPV_KHR_bfloat16], [BFloat16TypeKHR]>;
defm BFloat16CooperativeMatrixKHR : CapabilityOperand<5118, 0, 0, [SPV_KHR_bfloat16], [BFloat16TypeKHR, CooperativeMatrixKHR]>;
defm BlockingPipesALTERA : CapabilityOperand<5945, 0, 0, [SPV_ALTERA_blocking_pipes], []>;
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
new file mode 100644
index 0000000000000..899b6c7c526d7
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_bfloat16_load_store_xchg.ll
@@ -0,0 +1,38 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_bfloat16 %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_16bit_atomics,+SPV_KHR_bfloat16 %s -o - | FileCheck %s
+
+; CHECK-ERROR: LLVM ERROR: The atomic bfloat16 instruction requires the following SPIR-V extension: SPV_INTEL_16bit_atomics
+
+; CHECK-DAG: Capability BFloat16TypeKHR
+; CHECK-DAG: Capability AtomicBFloat16LoadStoreINTEL
+; CHECK-DAG: Extension "SPV_KHR_bfloat16"
+; CHECK-DAG: Extension "SPV_INTEL_16bit_atomics"
+; CHECK-DAG: %[[#TyBF16:]] = OpTypeFloat 16 0
+; CHECK-DAG: %[[#TyBF16Ptr:]] = OpTypePointer {{[a-zA-Z]+}} %[[#TyBF16]]
+; CHECK-DAG: %[[#TyInt32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Value42:]] = OpConstant %[[#TyBF16]] 16936{{$}}
+; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyBF16]]
+; CHECK-DAG: %[[#BF16Ptr:]] = OpVariable %[[#TyBF16Ptr]] CrossWorkgroup %[[#Const0]]
+; CHECK-DAG: %[[#ScopeDevice:]] = OpConstant %[[#TyInt32]] 1{{$}}
+; CHECK-DAG: %[[#MemSemAcqRel:]] = OpConstant %[[#TyInt32]] 528{{$}}
+; CHECK-DAG: %[[#ScopeAllSvmDevices:]] = OpConstantNull %[[#TyInt32]]
+; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
+
+; CHECK: OpAtomicLoad %[[#TyBF16]] %[[#BF16Ptr]] %[[#ScopeDevice]] %[[#MemSemAcqRel]]
+; CHECK: OpAtomicStore %[[#BF16Ptr]] %[[#ScopeDevice]] %[[#MemSemAcqRel]] %[[#Value42]]
+; CHECK: OpAtomicExchange %[[#TyBF16]] %[[#BF16Ptr]] %[[#ScopeAllSvmDevices]] %[[#MemSeqCst]] %[[#Value42]]
+
+
+ at val = common dso_local local_unnamed_addr addrspace(1) global bfloat 0.000000e+00, align 2
+
+define dso_local spir_func void @test_atomic_bfloat16_load_store_xchg() local_unnamed_addr {
+entry:
+ %load = call spir_func bfloat @atomic_load(ptr addrspace(1) @val)
+ call spir_func void @atomic_store(ptr addrspace(1) @val, bfloat 42.000000e+00)
+ %xchg = atomicrmw xchg ptr addrspace(1) @val, bfloat 42.000000e+00 seq_cst
+ ret void
+}
+
+declare spir_func bfloat @atomic_load(ptr addrspace(1))
+declare spir_func void @atomic_store(ptr addrspace(1), bfloat)
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_arithmetic.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_arithmetic.ll
new file mode 100644
index 0000000000000..13f9f8c80e87a
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_arithmetic.ll
@@ -0,0 +1,44 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_16bit_atomics %s -o - | FileCheck %s
+
+; CHECK-ERROR: LLVM ERROR: 16-bit integer atomic operations require the following SPIR-V extension: SPV_INTEL_16bit_atomics
+
+; CHECK-DAG: Capability Int16
+; CHECK-DAG: Capability Int16AtomicsINTEL
+; CHECK-DAG: Extension "SPV_INTEL_16bit_atomics"
+; CHECK-DAG: %[[#TyInt16:]] = OpTypeInt 16 0
+; CHECK-DAG: %[[#TyInt16Ptr:]] = OpTypePointer {{[a-zA-Z]+}} %[[#TyInt16]]
+; CHECK-DAG: %[[#TyInt32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Value5:]] = OpConstant %[[#TyInt16]] 5{{$}}
+; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyInt16]]
+; CHECK-DAG: %[[#Int16Ptr:]] = OpVariable %[[#TyInt16Ptr]] CrossWorkgroup %[[#Const0]]
+; CHECK-DAG: %[[#Scope:]] = OpConstantNull %[[#TyInt32]]
+; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
+
+; CHECK: OpAtomicIAdd %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicISub %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicUMin %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicUMax %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicSMin %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicSMax %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicAnd %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicOr %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+; CHECK: OpAtomicXor %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value5]]
+
+
+ at val = common dso_local local_unnamed_addr addrspace(1) global i16 0, align 2
+
+define dso_local spir_func void @test_atomic_int16_arithmetic() local_unnamed_addr {
+entry:
+ %add = atomicrmw add ptr addrspace(1) @val, i16 5 seq_cst
+ %sub = atomicrmw sub ptr addrspace(1) @val, i16 5 seq_cst
+ %umin = atomicrmw umin ptr addrspace(1) @val, i16 5 seq_cst
+ %umax = atomicrmw umax ptr addrspace(1) @val, i16 5 seq_cst
+ %smin = atomicrmw min ptr addrspace(1) @val, i16 5 seq_cst
+ %smax = atomicrmw max ptr addrspace(1) @val, i16 5 seq_cst
+ %and = atomicrmw and ptr addrspace(1) @val, i16 5 seq_cst
+ %or = atomicrmw or ptr addrspace(1) @val, i16 5 seq_cst
+ %xor = atomicrmw xor ptr addrspace(1) @val, i16 5 seq_cst
+ ret void
+}
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
new file mode 100644
index 0000000000000..bd74fe212b144
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_16bit_atomics/atomic_int16_load_store_xchg_cmpxchg.ll
@@ -0,0 +1,31 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_16bit_atomics %s -o - | FileCheck %s
+
+; CHECK-ERROR: LLVM ERROR: 16-bit integer atomic operations require the following SPIR-V extension: SPV_INTEL_16bit_atomics
+
+; CHECK-DAG: Capability Int16
+; CHECK-DAG: Capability AtomicInt16CompareExchangeINTEL
+; CHECK-DAG: Extension "SPV_INTEL_16bit_atomics"
+; CHECK-DAG: %[[#TyInt16:]] = OpTypeInt 16 0
+; CHECK-DAG: %[[#TyInt16Ptr:]] = OpTypePointer {{[a-zA-Z]+}} %[[#TyInt16]]
+; CHECK-DAG: %[[#TyInt32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Value1:]] = OpConstant %[[#TyInt16]] 1{{$}}
+; CHECK-DAG: %[[#Value42:]] = OpConstant %[[#TyInt16]] 42{{$}}
+; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyInt16]]
+; CHECK-DAG: %[[#Int16Ptr:]] = OpVariable %[[#TyInt16Ptr]] CrossWorkgroup %[[#Const0]]
+; CHECK-DAG: %[[#Scope:]] = OpConstantNull %[[#TyInt32]]
+; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
+
+; CHECK: OpAtomicExchange %[[#TyInt16]] %[[#Int16Ptr]] %[[#Scope]] %[[#MemSeqCst]] %[[#Value42]]
+; CHECK: OpAtomicCompareExchange %[[#TyInt16]] %[[#]] %[[#Scope]] %[[#MemSeqCst]] %[[#MemSeqCst]] %[[#Value42]] %[[#Value1]]
+
+
+ at val = common dso_local local_unnamed_addr addrspace(1) global i16 0, align 2
+
+define dso_local spir_func void @test_atomic_int16_basic() local_unnamed_addr {
+entry:
+ %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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/184312
More information about the llvm-commits
mailing list