[clang] [llvm] [SPIRV] Conditionally define `__AMDGCN_UNSAFE_FP_ATOMICS__` for AMDGCN flavoured SPIR-V (PR #192136)
Alex Voicu via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 10:23:33 PDT 2026
https://github.com/AlexVlx updated https://github.com/llvm/llvm-project/pull/192136
>From c0933bf40cee4ed34a14c6b70cab9950194ad6d3 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Tue, 9 Dec 2025 21:44:27 +0000
Subject: [PATCH 1/7] i128 is legal in IR / MIR, even though it might yield a
module which requires extensions.
---
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 17 +++++++++--------
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 4 ++--
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 2078bfee2e767..73e813ef53094 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -115,18 +115,19 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
v4s1, v4s8, v4s16, v4s32, v4s64};
auto allScalarsAndVectors = {
- s1, s8, s16, s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64,
- v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64,
- v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
+ s1, s8, s16, s32, s64, s128, v2s1, v2s8, v2s16, v2s32,
+ v2s64, v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32,
+ v4s64, v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32,
+ v16s64};
- auto allIntScalarsAndVectors = {s8, s16, s32, s64, v2s8, v2s16,
- v2s32, v2s64, v3s8, v3s16, v3s32, v3s64,
- v4s8, v4s16, v4s32, v4s64, v8s8, v8s16,
- v8s32, v8s64, v16s8, v16s16, v16s32, v16s64};
+ auto allIntScalarsAndVectors = {
+ s8, s16, s32, s64, s128, v2s8, v2s16, v2s32, v2s64, v3s8,
+ v3s16, v3s32, v3s64, v4s8, v4s16, v4s32, v4s64, v8s8, v8s16, v8s32,
+ v8s64, v16s8, v16s16, v16s32, v16s64};
auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1};
- auto allIntScalars = {s8, s16, s32, s64};
+ auto allIntScalars = {s8, s16, s32, s64, s128};
auto allFloatScalarsAndF16Vector2AndVector4s = {s16, s32, s64, v2s16, v4s16};
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index acc726717743d..9ddbeee92ffb6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -388,11 +388,11 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
// To support current approach and limitations wrt. bit width here we widen a
// scalar register with a bit width greater than 1 to valid sizes and cap it to
-// 64 width.
+// 128 width.
static unsigned widenBitWidthToNextPow2(unsigned BitWidth) {
if (BitWidth == 1)
return 1; // No need to widen 1-bit values
- return std::min(std::max(1u << Log2_32_Ceil(BitWidth), 8u), 64u);
+ return std::min(std::max(1u << Log2_32_Ceil(BitWidth), 8u), 128u);
}
static void widenScalarType(Register Reg, MachineRegisterInfo &MRI) {
>From 82dbfe9ac050698e040cfacf5bc1ea4125901518 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Tue, 9 Dec 2025 21:54:01 +0000
Subject: [PATCH 2/7] Fix formatting.
---
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 73e813ef53094..30703ee40be06 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -115,15 +115,15 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
v4s1, v4s8, v4s16, v4s32, v4s64};
auto allScalarsAndVectors = {
- s1, s8, s16, s32, s64, s128, v2s1, v2s8, v2s16, v2s32,
- v2s64, v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32,
- v4s64, v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32,
- v16s64};
+ s1, s8, s16, s32, s64, s128, v2s1, v2s8,
+ v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, v3s32, v3s64,
+ v4s1, v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16,
+ v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
auto allIntScalarsAndVectors = {
- s8, s16, s32, s64, s128, v2s8, v2s16, v2s32, v2s64, v3s8,
- v3s16, v3s32, v3s64, v4s8, v4s16, v4s32, v4s64, v8s8, v8s16, v8s32,
- v8s64, v16s8, v16s16, v16s32, v16s64};
+ s8, s16, s32, s64, s128, v2s8, v2s16, v2s32, v2s64,
+ v3s8, v3s16, v3s32, v3s64, v4s8, v4s16, v4s32, v4s64, v8s8,
+ v8s16, v8s32, v8s64, v16s8, v16s16, v16s32, v16s64};
auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1};
>From 97d5cc2eaa4db8027ecb6f038b356231c745c0a8 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Mon, 15 Dec 2025 17:59:30 +0000
Subject: [PATCH 3/7] Handle storing of aggregates via `spv_store`.
---
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 13 ++++++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 10 +++++++
.../SPIRV/instructions/nested-composites.ll | 30 +++++++++++++++++++
3 files changed, 53 insertions(+)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 9b34ff90abe69..73dcec062d3f0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2021,6 +2021,19 @@ Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
MachineMemOperand::Flags Flags =
TLI->getStoreMemOperandFlags(I, CurrF->getDataLayout());
auto *PtrOp = I.getPointerOperand();
+
+ if (I.getValueOperand()->getType()->isAggregateType()) {
+ // It is possible that what used to be an ExtractValueInst has been replaced
+ // with a call to the spv_extractv intrinsic, and that said call hasn't
+ // had its return type replaced with i32 during the dedicated pass (because
+ // it was emitted later); we have to handle this here, because IRTranslator
+ // cannot deal with multi-register types at the moment.
+ CallBase *CB = dyn_cast<CallBase>(I.getValueOperand());
+ assert(CB && CB->getIntrinsicID() == Intrinsic::spv_extractv &&
+ "Unexpected argument of aggregate type, should be spv_extractv!");
+ CB->mutateType(B.getInt32Ty());
+ }
+
auto *NewI = B.CreateIntrinsic(
Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
{I.getValueOperand(), PtrOp, B.getInt16(Flags),
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 2e4563795e8f0..dd2e3f1951850 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3297,6 +3297,16 @@ bool SPIRVInstructionSelector::selectInsertVal(Register ResVReg,
bool SPIRVInstructionSelector::selectExtractVal(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {
+ Type *MaybeResTy = nullptr;
+ StringRef ResName;
+ if (GR.findValueAttrs(&I, MaybeResTy, ResName) &&
+ MaybeResTy != GR.getTypeForSPIRVType(ResType)) {
+ assert(!MaybeResTy || MaybeResTy->isAggregateType() &&
+ "Expected aggregate type for extractv instruction");
+ ResType = GR.getOrCreateSPIRVType(MaybeResTy, I,
+ SPIRV::AccessQualifier::ReadWrite, false);
+ GR.assignSPIRVTypeToVReg(ResType, ResVReg, *I.getMF());
+ }
MachineBasicBlock &BB = *I.getParent();
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
.addDef(ResVReg)
diff --git a/llvm/test/CodeGen/SPIRV/instructions/nested-composites.ll b/llvm/test/CodeGen/SPIRV/instructions/nested-composites.ll
index 88e992f183452..7b49002766a26 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/nested-composites.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/nested-composites.ll
@@ -1,13 +1,19 @@
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK-DAG: OpName [[FOOBAR:%.+]] "foobar"
; CHECK-DAG: OpName [[PRODUCER:%.+]] "producer"
; CHECK-DAG: OpName [[CONSUMER:%.+]] "consumer"
+; CHECK-DAG: OpName [[SNEAKY:%.+]] "sneaky"
+; CHECK-DAG: OpName [[ARR_RET:%.+]] "arr_ret"
; CHECK-NOT: DAG-FENCE
%ty1 = type {i16, i32}
%ty2 = type {%ty1, i64}
+%ty3 = type {ptr addrspace(4), ptr addrspace(4), [8 x i8]}
; CHECK-DAG: [[I16:%.+]] = OpTypeInt 16
; CHECK-DAG: [[I32:%.+]] = OpTypeInt 32
@@ -18,6 +24,12 @@
; CHECK-DAG: [[UNDEF_I64:%.+]] = OpUndef [[I64]]
; CHECK-DAG: [[UNDEF_TY2:%.+]] = OpUndef [[TY2]]
; CHECK-DAG: [[CST_42:%.+]] = OpConstant [[I32]] 42
+; CHECK-DAG: [[I8:%.+]] = OpTypeInt 8 0
+; CHECK-DAG: [[PTR:%.+]] = OpTypePointer Generic [[I8]]
+; CHECK-DAG: [[CST_8:%.+]] = OpConstant [[I32]] 8
+; CHECK-DAG: [[ARR:%.+]] = OpTypeArray [[I8]] [[CST_8]]
+; CHECK-DAG: [[TY3:%.+]] = OpTypeStruct [[PTR]] [[PTR]] [[ARR]]
+; CHECK-DAG: [[PTR_ARR:%.+]] = OpTypePointer Generic [[ARR]]
; CHECK-NOT: DAG-FENCE
@@ -62,3 +74,21 @@ define i32 @consumer(%ty2 %agg) {
; CHECK: [[RET:%.+]] = OpCompositeExtract [[I32]] [[AGG]] 0 1
; CHECK: OpReturnValue [[RET]]
; CHECK: OpFunctionEnd
+
+declare %ty3 @arr_ret()
+
+define void @sneaky(ptr addrspace(4) %p, [8 x i8] %a) {
+ %1 = call spir_func %ty3 @arr_ret()
+ %2 = getelementptr inbounds nuw %ty3, ptr addrspace(4) %p, i32 0, i32 2
+ %3 = extractvalue %ty3 %1, 2
+ store [8 x i8] %3, ptr addrspace(4) %2, align 8
+ ret void
+}
+
+; CHECK: [[SNEAKY]] = OpFunction
+; CHECK: [[PTR_AGG:%.+]] = OpFunctionParameter
+; CHECK: [[A:%.+]] = OpFunctionParameter [[ARR]]
+; CHECK: [[AGG_RET:%.+]] = OpFunctionCall [[TY3]]
+; CHECK: [[GEP:%.+]] = OpInBoundsPtrAccessChain [[PTR_ARR]] [[PTR_AGG]]
+; CHECK: [[EXTRACTV:%.+]] = OpCompositeExtract [[ARR]] [[AGG_RET]] 2
+; CHECK: OpStore [[GEP]] [[EXTRACTV]]
>From f837bb69c73c38dc2c628fe1e83b87526bd8d4d8 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Mon, 15 Dec 2025 18:46:39 +0000
Subject: [PATCH 4/7] Fix formatting.
---
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index dd2e3f1951850..77c4678bb2210 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3301,8 +3301,9 @@ bool SPIRVInstructionSelector::selectExtractVal(Register ResVReg,
StringRef ResName;
if (GR.findValueAttrs(&I, MaybeResTy, ResName) &&
MaybeResTy != GR.getTypeForSPIRVType(ResType)) {
- assert(!MaybeResTy || MaybeResTy->isAggregateType() &&
- "Expected aggregate type for extractv instruction");
+ assert(!MaybeResTy ||
+ MaybeResTy->isAggregateType() &&
+ "Expected aggregate type for extractv instruction");
ResType = GR.getOrCreateSPIRVType(MaybeResTy, I,
SPIRV::AccessQualifier::ReadWrite, false);
GR.assignSPIRVTypeToVReg(ResType, ResVReg, *I.getMF());
>From 610c2971b9c16e8ce2b75f5e4bd8430596926f64 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Thu, 19 Mar 2026 00:25:37 +0000
Subject: [PATCH 5/7] Add `llvm.spv.named.boolean.spec.constant` intrinsic.
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 5 +++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 +++++++++++++
.../CodeGen/SPIRV/constant/spec-constant.ll | 21 ++++++++++++++++++-
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 5d467adb08c3d..51cb430f4bd43 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -43,6 +43,11 @@ let TargetPrefix = "spv" in {
def int_spv_alloca_array : Intrinsic<[llvm_any_ty], [llvm_anyint_ty, llvm_i32_ty], [ImmArg<ArgIndex<1>>]>;
def int_spv_undef : Intrinsic<[llvm_i32_ty], []>;
def int_spv_inline_asm : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, llvm_vararg_ty]>;
+ def int_spv_named_boolean_spec_constant
+ : Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_i1_ty, llvm_metadata_ty],
+ [ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>]>;
+ // TODO: possibly add intrinsics for other types of Spec Constants and a
+ // corresponding Clang builtin.
// Masked Gather/Scatter (SPV_INTEL_masked_gather_scatter)
def int_spv_masked_gather : Intrinsic<[llvm_any_ty],
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index eb30002d2e1a5..c045ab693e9ab 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -4125,6 +4125,20 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
MIB.constrainAllUses(TII, TRI, RBI);
return true;
}
+ case Intrinsic::spv_named_boolean_spec_constant: {
+ auto Opcode = I.getOperand(3).getImm()
+ ? SPIRV::OpSpecConstantTrue : SPIRV::OpSpecConstantFalse;
+
+ auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(I.getOperand(0).getReg())
+ .addUse(GR.getSPIRVTypeID(ResType));
+ MIB.constrainAllUses(TII, TRI, RBI);
+ unsigned SpecId = I.getOperand(2).getImm();
+ buildOpDecorate(I.getOperand(0).getReg(), *MIB.getInstr(), TII,
+ SPIRV::Decoration::SpecId, {SpecId});
+
+ return true;
+ }
case Intrinsic::spv_const_composite: {
// If no values are attached, the composite is null constant.
bool IsNull = I.getNumExplicitDefs() + 1 == I.getNumExplicitOperands();
diff --git a/llvm/test/CodeGen/SPIRV/constant/spec-constant.ll b/llvm/test/CodeGen/SPIRV/constant/spec-constant.ll
index 299d61d3bffde..5ca7a504addf7 100644
--- a/llvm/test/CodeGen/SPIRV/constant/spec-constant.ll
+++ b/llvm/test/CodeGen/SPIRV/constant/spec-constant.ll
@@ -8,6 +8,8 @@
; CHECK-DAG: OpDecorate [[float_const:%[0-9]+]] SpecId 8
; CHECK-DAG: OpDecorate [[double_const:%[0-9]+]] SpecId 9
; CHECK-DAG: OpDecorate [[enum_const:%[0-9]+]] SpecId 10
+; CHECK-DAG: OpDecorate [[named_bool_const_true:%[0-9]+]] SpecId 11
+; CHECK-DAG: OpDecorate [[named_bool_const_false:%[0-9]+]] SpecId 12
; CHECK-DAG: [[bool_const]] = OpSpecConstantTrue {{%[0-9]+}}
; CHECK-DAG: [[short_const]] = OpSpecConstant {{%[0-9]+}} 4
@@ -16,6 +18,8 @@
; CHECK-DAG: [[float_const]] = OpSpecConstant {{%[0-9]+}} 1112014848
; CHECK-DAG: [[double_const]] = OpSpecConstant {{%[0-9]+}} 0 1079574528
; CHECK-DAG: [[enum_const]] = OpSpecConstant {{%[0-9]+}} 30
+; CHECK-DAG: [[named_bool_const_true:%[0-9]+]] = OpSpecConstantTrue {{%[0-9]+}}
+; CHECK-DAG: [[named_bool_const_false:%[0-9]+]] = OpSpecConstantFalse {{%[0-9]+}}
@_ZL10bool_const = internal addrspace(10) global i32 0, align 4
@_ZL11short_const = internal addrspace(10) global i16 0, align 2
@@ -58,6 +62,18 @@ entry:
; CHECK: OpStore {{%[0-9]+}} [[enum_const]]
%18 = tail call spir_func i32 @_Z20__spirv_SpecConstantii(i32 10, i32 30)
store i32 %18, ptr addrspace(10) @_ZL10enum_const, align 4
+
+ ; CHECK: [[bt:%[0-9]+]] = OpSelect {{%[0-9]+}} [[named_bool_const_true]]
+ ; CHECK: OpStore {{%[0-9]+}} [[bt]]
+ %19 = tail call spir_func i1 @llvm.spv.named.boolean.spec.constant(i32 11, i1 true, metadata !{})
+ %zext_0 = zext i1 %19 to i32
+ store i32 %zext_0, ptr addrspace(10) @_ZL10bool_const, align 4
+
+ ; CHECK: [[bf:%[0-9]+]] = OpSelect {{%[0-9]+}} [[named_bool_const_false]]
+ ; CHECK: OpStore {{%[0-9]+}} [[bf]]
+ %20 = tail call spir_func i1 @llvm.spv.named.boolean.spec.constant(i32 12, i1 false, metadata !{})
+ %zext_1 = zext i1 %20 to i32
+ store i32 %zext_1, ptr addrspace(10) @_ZL10bool_const, align 4
ret void
}
@@ -69,5 +85,8 @@ declare i32 @_Z20__spirv_SpecConstantii(i32, i32)
declare i64 @_Z20__spirv_SpecConstantix(i32, i64)
declare float @_Z20__spirv_SpecConstantif(i32, float)
declare double @_Z20__spirv_SpecConstantid(i32, double)
+declare i1 @llvm.spv.named.boolean.spec.constant(i32, i1, metadata)
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
-attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
\ No newline at end of file
+!0 = !{ !"" }
\ No newline at end of file
>From 9544c96e85c5b7ff427f9b977ee8b704f8b81f93 Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Thu, 19 Mar 2026 00:54:52 +0000
Subject: [PATCH 6/7] Fix formatting.
---
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index c045ab693e9ab..88169df9ba61c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -4126,8 +4126,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
return true;
}
case Intrinsic::spv_named_boolean_spec_constant: {
- auto Opcode = I.getOperand(3).getImm()
- ? SPIRV::OpSpecConstantTrue : SPIRV::OpSpecConstantFalse;
+ auto Opcode = I.getOperand(3).getImm() ? SPIRV::OpSpecConstantTrue
+ : SPIRV::OpSpecConstantFalse;
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
.addDef(I.getOperand(0).getReg())
>From aa1be1fb95eab1f854f3c2743f5d88bc7189ee6b Mon Sep 17 00:00:00 2001
From: Alex Voicu <alexandru.voicu at amd.com>
Date: Tue, 14 Apr 2026 20:52:49 +0100
Subject: [PATCH 7/7] Define `__AMDGCN_UNSAFE_FP_ATOMICS__` for AMDGCN
flavoured SPIR-V when required.
---
clang/lib/Basic/Targets/SPIR.cpp | 3 +++
clang/test/Preprocessor/predefined-macros.c | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp
index 19f160e279b21..7726c95cc7392 100644
--- a/clang/lib/Basic/Targets/SPIR.cpp
+++ b/clang/lib/Basic/Targets/SPIR.cpp
@@ -145,6 +145,9 @@ void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AMD__");
Builder.defineMacro("__AMDGPU__");
Builder.defineMacro("__AMDGCN__");
+
+ if (Opts.AtomicIgnoreDenormalMode)
+ Builder.defineMacro("__AMDGCN_UNSAFE_FP_ATOMICS__");
}
void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) {
diff --git a/clang/test/Preprocessor/predefined-macros.c b/clang/test/Preprocessor/predefined-macros.c
index da25b1efa3984..8dbb477be4c5d 100644
--- a/clang/test/Preprocessor/predefined-macros.c
+++ b/clang/test/Preprocessor/predefined-macros.c
@@ -240,14 +240,18 @@
// RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spirv64-amd-amdhsa \
// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIRV64-AMDGCN
+// RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spirv64-amd-amdhsa -fatomic-ignore-denormal-mode \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIRV64-AMDGCN-UNSAFE-FP-ATOMICS
// CHECK-SPIRV64-AMDGCN-DAG: #define __IMAGE_SUPPORT__ 1
// CHECK-SPIRV64-AMDGCN-DAG: #define __SPIRV__ 1
// CHECK-SPIRV64-AMDGCN-DAG: #define __SPIRV64__ 1
// CHECK-SPIRV64-AMDGCN-DAG: #define __AMD__ 1
// CHECK-SPIRV64-AMDGCN-DAG: #define __AMDGCN__ 1
// CHECK-SPIRV64-AMDGCN-DAG: #define __AMDGPU__ 1
+// CHECK-SPIRV64-AMDGCN-NOT: #define __AMDGCN_UNSAFE_FP_ATOMICS__
// CHECK-SPIRV64-AMDGCN-NOT: #define __SPIRV32__ 1
// CHECK-SPIRV64-AMDGCN-NOT: #define __spirv__ 1
+// CHECK-SPIRV64-AMDGCN-UNSAFE-FP-ATOMICS: #define __AMDGCN_UNSAFE_FP_ATOMICS__ 1
// RUN: %clang_cc1 %s -E -dM -o - -x hip -triple x86_64-unknown-linux-gnu \
// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-HIP
More information about the cfe-commits
mailing list