[SPIR-V] Complete SPV_INTEL_16bit_atomics extension support (#184312)

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
This commit is contained in:
Viktoria Maximova 2026-03-19 11:34:57 +01:00 committed by GitHub
parent e122a2d531
commit eaf04be341
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 190 additions and 22 deletions

View File

@ -1421,7 +1421,8 @@ void addInstrRequirements(const MachineInstr &MI,
SPIRV::ModuleAnalysisInfo &MAI,
const SPIRVSubtarget &ST) {
SPIRV::RequirementHandler &Reqs = MAI.Reqs;
switch (MI.getOpcode()) {
unsigned Op = MI.getOpcode();
switch (Op) {
case SPIRV::OpMemoryModel: {
int64_t Addr = MI.getOperand(0).getImm();
Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
@ -1628,7 +1629,7 @@ void addInstrRequirements(const MachineInstr &MI,
case SPIRV::OpAtomicXor: {
const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
const MachineInstr *InstrPtr = &MI;
if (MI.getOpcode() == SPIRV::OpAtomicStore) {
if (Op == SPIRV::OpAtomicStore) {
assert(MI.getOperand(3).isReg());
InstrPtr = MRI.getVRegDef(MI.getOperand(3).getReg());
assert(InstrPtr && "Unexpected type instruction for OpAtomicStore");
@ -1636,10 +1637,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);
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 (is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
SPIRV::OpAtomicExchange},
Op)) {
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;
}
@ -2002,8 +2037,7 @@ void addInstrRequirements(const MachineInstr &MI,
{SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
{SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
const auto OpCode = MI.getOpcode();
const unsigned LayoutNum = LayoutToInstMap[OpCode];
const unsigned LayoutNum = LayoutToInstMap[Op];
Register RegLayout = MI.getOperand(LayoutNum).getReg();
const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
MachineInstr *MILayout = MRI.getUniqueVRegDef(RegLayout);
@ -2021,12 +2055,12 @@ void addInstrRequirements(const MachineInstr &MI,
}
// Nothing to do.
if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
if (Op == SPIRV::OpCooperativeMatrixLoadKHR ||
Op == SPIRV::OpCooperativeMatrixStoreKHR)
break;
std::string InstName;
switch (OpCode) {
switch (Op) {
case SPIRV::OpCooperativeMatrixPrefetchINTEL:
InstName = "OpCooperativeMatrixPrefetchINTEL";
break;
@ -2045,7 +2079,7 @@ void addInstrRequirements(const MachineInstr &MI,
report_fatal_error(ErrorMsg.c_str(), false);
}
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
if (Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
Reqs.addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
break;
}
@ -2090,17 +2124,17 @@ void addInstrRequirements(const MachineInstr &MI,
SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
SPIRV::AddressingModel::AddressingModel AddrModel = MAI.Addr;
SPIRVTypeInst TyDef = GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg());
if (MI.getOpcode() == SPIRV::OpConvertHandleToImageINTEL &&
if (Op == SPIRV::OpConvertHandleToImageINTEL &&
TyDef->getOpcode() != SPIRV::OpTypeImage) {
report_fatal_error("Incorrect return type for the instruction "
"OpConvertHandleToImageINTEL",
false);
} else if (MI.getOpcode() == SPIRV::OpConvertHandleToSamplerINTEL &&
} else if (Op == SPIRV::OpConvertHandleToSamplerINTEL &&
TyDef->getOpcode() != SPIRV::OpTypeSampler) {
report_fatal_error("Incorrect return type for the instruction "
"OpConvertHandleToSamplerINTEL",
false);
} else if (MI.getOpcode() == SPIRV::OpConvertHandleToSampledImageINTEL &&
} else if (Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
TyDef->getOpcode() != SPIRV::OpTypeSampledImage) {
report_fatal_error("Incorrect return type for the instruction "
"OpConvertHandleToSampledImageINTEL",
@ -2133,12 +2167,11 @@ void addInstrRequirements(const MachineInstr &MI,
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
const auto OpCode = MI.getOpcode();
if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
if (Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
break;
}
if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
if (Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
break;
}

View File

@ -518,6 +518,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]>;
@ -576,12 +577,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]>;
@ -622,7 +626,6 @@ 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 MaskedGatherScatterINTEL : CapabilityOperand<6427, 0, 0, [SPV_INTEL_masked_gather_scatter], []>;
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], []>;

View File

@ -0,0 +1,42 @@
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_bfloat16 %s -o /dev/null 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 CrossWorkgroup %[[#TyBF16]]
; 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: %[[#MemSemAcqRel:]] = OpConstant %[[#TyInt32]] 528{{$}}
; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
; CHECK-DAG: %[[#Val:]] = OpVariable %[[#TyBF16Ptr]] CrossWorkgroup %[[#Const0]]
; CHECK: OpAtomicLoad %[[#TyBF16]] %[[#Val]] %[[#ScopeDevice]] %[[#MemSemAcqRel]]
; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeDevice]] %[[#MemSemAcqRel]] %[[#Const42]]
; CHECK: OpAtomicExchange %[[#TyBF16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSeqCst]] %[[#Const42]]
@val = private addrspace(1) global bfloat 0.000000e+00
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)
%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)

View File

@ -0,0 +1,44 @@
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 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: %[[#TyInt32:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#TyInt16Ptr:]] = OpTypePointer CrossWorkgroup %[[#TyInt16]]
; CHECK-DAG: %[[#Const5:]] = OpConstant %[[#TyInt16]] 5{{$}}
; CHECK-DAG: %[[#Const0:]] = OpConstantNull %[[#TyInt16]]
; CHECK-DAG: %[[#Scope:]] = OpConstantNull %[[#TyInt32]]
; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
; CHECK-DAG: %[[#Val:]] = OpVariable %[[#TyInt16Ptr]] CrossWorkgroup %[[#Const0]]
; CHECK: OpAtomicIAdd %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicISub %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicUMin %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicUMax %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicSMin %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicSMax %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicAnd %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicOr %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
; CHECK: OpAtomicXor %[[#TyInt16]] %[[#Val]] %[[#Scope]] %[[#MemSeqCst]] %[[#Const5]]
@val = private addrspace(1) global i16 0
define spir_func void @test_atomic_int16_arithmetic() {
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
}

View File

@ -0,0 +1,44 @@
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o /dev/null 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 CrossWorkgroup %[[#TyInt16]]
; CHECK-DAG: %[[#TyInt32:]] = OpTypeInt 32 0
; 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: %[[#MemSemAcqRel:]] = OpConstant %[[#TyInt32]] 528{{$}}
; CHECK-DAG: %[[#MemSeqCst:]] = OpConstant %[[#TyInt32]] 16{{$}}
; CHECK-DAG: %[[#Val:]] = OpVariable %[[#TyInt16Ptr]] CrossWorkgroup %[[#Const0]]
; CHECK: OpAtomicLoad %[[#TyInt16]] %[[#Val]] %[[#ScopeDevice]] %[[#MemSemAcqRel]]
; CHECK: OpAtomicStore %[[#Val]] %[[#ScopeDevice]] %[[#MemSemAcqRel]] %[[#Const42]]
; CHECK: OpAtomicExchange %[[#TyInt16]] %[[#Val]] %[[#ScopeAllSvmDevices]] %[[#MemSeqCst]] %[[#Const42]]
; CHECK: OpAtomicCompareExchange %[[#TyInt16]] %[[#]] %[[#ScopeAllSvmDevices]] %[[#MemSeqCst]] %[[#MemSeqCst]] %[[#Const42]] %[[#Const1]]
@val = private addrspace(1) global i16 0
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)
%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)

View File

@ -2,6 +2,7 @@
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_KHR_bfloat16 %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR2
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_INTEL_16bit_atomics,+SPV_KHR_bfloat16,+SPV_INTEL_bfloat16_arithmetic %s -o - | FileCheck %s
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-vulkan --spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_INTEL_16bit_atomics,+SPV_KHR_bfloat16,+SPV_INTEL_bfloat16_arithmetic %s -o - | FileCheck %s
; CHECK-ERROR1: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_add
; CHECK-ERROR2: LLVM ERROR: The atomic bfloat16 instruction requires the following SPIR-V extension: SPV_INTEL_16bit_atomics
@ -15,7 +16,7 @@
; CHECK-DAG: %[[TyBF16Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyBF16]]
; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK-DAG: %[[ConstBF16:[0-9]+]] = OpConstant %[[TyBF16]] 16936{{$}}
; CHECK-DAG: %[[Const0:[0-9]+]] = OpConstantNull %[[TyBF16]]
; CHECK-DAG: %[[Const0:[0-9]+]] = {{OpConstantNull|OpConstant}} %[[TyBF16]]{{( 0)?}}
; CHECK-DAG: %[[BF16Ptr:[0-9]+]] = OpVariable %[[TyBF16Ptr]] CrossWorkgroup %[[Const0]]
; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
@ -24,9 +25,9 @@
; CHECK: OpAtomicFAddEXT %[[TyBF16]] %[[BF16Ptr]] %[[ScopeAllSvmDevices]] %[[MemSeqCst]] %[[NegatedConstBF16]]
@f = common dso_local local_unnamed_addr addrspace(1) global bfloat 0.000000e+00, align 8
@f = private addrspace(1) global bfloat 0.000000e+00
define dso_local spir_func void @test1() local_unnamed_addr {
define spir_func void @test1() {
entry:
%addval = atomicrmw fadd ptr addrspace(1) @f, bfloat 42.000000e+00 seq_cst
%subval = atomicrmw fsub ptr addrspace(1) @f, bfloat 42.000000e+00 seq_cst

View File

@ -1,5 +1,6 @@
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_min_max,+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_EXT_shader_atomic_float_min_max,+SPV_INTEL_16bit_atomics,+SPV_KHR_bfloat16 %s -o - | FileCheck %s
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-vulkan --spirv-ext=+SPV_EXT_shader_atomic_float_min_max,+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
@ -11,14 +12,14 @@
; CHECK-DAG: %[[TyBF16Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyBF16]]
; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK-DAG: %[[ConstBF16:[0-9]+]] = OpConstant %[[TyBF16]] 16936{{$}}
; CHECK-DAG: %[[Const0:[0-9]+]] = OpConstantNull %[[TyBF16]]
; CHECK-DAG: %[[Const0:[0-9]+]] = {{OpConstantNull|OpConstant}} %[[TyBF16]]{{( 0)?}}
; CHECK-DAG: %[[BF16Ptr:[0-9]+]] = OpVariable %[[TyBF16Ptr]] CrossWorkgroup %[[Const0]]
; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
; CHECK: OpAtomicFMinEXT %[[TyBF16]] %[[BF16Ptr]] %[[ScopeAllSvmDevices]] %[[MemSeqCst]] %[[ConstBF16]]
; CHECK: OpAtomicFMaxEXT %[[TyBF16]] %[[BF16Ptr]] %[[ScopeAllSvmDevices]] %[[MemSeqCst]] %[[ConstBF16]]
@f = common dso_local local_unnamed_addr addrspace(1) global bfloat 0.000000e+00, align 8
@f = private addrspace(1) global bfloat 0.000000e+00
define spir_func void @test1() {
entry: