[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