https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/212945
>From 30aafd800b8b23fcf3035082226cb8a71c584d2c Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Tue, 28 Jul 2026 12:14:57 +0200 Subject: [PATCH] AMDGPU: Tablegenerate TargetParser feature sets Traditionally we maintained 2 parallel feature mechanisms, one in clang (later moved to TargetParser), with largely mirrored subtarget features defined in the backend. Start directly taking feature information from the backend and putting it into TargetParser. This is still in a compromise mid-migration state. We still have both the legacy "ArchAttr" bitfield integer, plus a new AMDGPUFeatureBitset field stored in the table, which isn't yet exported. For the moment, the new bitset is only used to populate the feature string name map, which is the big maintainability win. This also lists an explicit subset of exported features to avoid churn. Co-authored-by: Claude (Claude-Opus-4.8) --- clang/test/CodeGen/link-builtin-bitcode.c | 6 +- llvm/lib/Target/AMDGPU/AMDGPU.td | 39 ++ llvm/lib/TargetParser/AMDGPUTargetParser.cpp | 559 ++---------------- .../TargetParser/TargetParserTest.cpp | 43 ++ .../TableGen/Basic/AMDGPUTargetDefEmitter.cpp | 118 +++- 5 files changed, 251 insertions(+), 514 deletions(-) diff --git a/clang/test/CodeGen/link-builtin-bitcode.c b/clang/test/CodeGen/link-builtin-bitcode.c index 8a6aebdbd66dd..d15463d785f1a 100644 --- a/clang/test/CodeGen/link-builtin-bitcode.c +++ b/clang/test/CodeGen/link-builtin-bitcode.c @@ -44,6 +44,6 @@ int bar() { return no_attr() + attr_in_target() + attr_not_in_target() + attr_in // CHECK-SAME: () #[[ATTR_INCOMPATIBLE:[0-9]+]] { // CHECK: attributes #[[ATTR_BAR]] = { {{.*}} "no-trapping-math"="true" {{.*}} } -// CHECK: attributes #[[ATTR_COMPATIBLE]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64" } -// CHECK: attributes #[[ATTR_EXTEND]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dot8-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64" } -// CHECK: attributes #[[ATTR_INCOMPATIBLE]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64,-gfx9-insts" } +// CHECK: attributes #[[ATTR_COMPATIBLE]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+cvt-pknorm-vop3-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64" } +// CHECK: attributes #[[ATTR_EXTEND]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+cvt-pknorm-vop3-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dot8-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64" } +// CHECK: attributes #[[ATTR_INCOMPATIBLE]] = { {{.*}} "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+atomic-fmin-fmax-global-f64,+ci-insts,+cube-insts,+cvt-pknorm-vop2-insts,+cvt-pknorm-vop3-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+flat-global-insts,+gfx8-insts,+gfx90a-insts,+gws,+image-insts,+lerp-inst,+mai-insts,+mqsad-insts,+mqsad-pk-insts,+msad-insts,+qsad-insts,+s-memrealtime,+s-memtime-inst,+sad-insts,+vmem-to-lds-load-insts,+wavefrontsize64,-gfx9-insts" } diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index 8eba93af714dc..8d87f700f65d7 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -2990,6 +2990,45 @@ def WaveSizeVT : ValueTypeByHwMode<[ AlignedVGPRNoAGPRMode_Wave32], [i64, i64, i64, i32, i32]>; +// The subset of SubtargetFeatures which should be exposed outside of +// the backend. +def AMDGPUFrontendVisibleFeatures { + list<SubtargetFeature> Features = [ + Feature16BitInsts, FeatureAddMinMaxInsts, FeatureAshrPkInsts, + FeatureAsyncLoadToLDSInsts, FeatureAsyncStoreFromLDSInsts, FeatureAsynccnt, + FeatureAtomicBufferGlobalPkAddF16Insts, FeatureAtomicBufferPkAddBF16Inst, FeatureAtomicDsPkAdd16Insts, + FeatureAtomicFMinFMaxF32GlobalInsts, FeatureAtomicFMinFMaxF64GlobalInsts, FeatureAtomicFaddRtnInsts, + FeatureAtomicFlatPkAdd16Insts, FeatureAtomicGlobalPkAddBF16Inst, FeatureBF16ConversionInsts, + FeatureBF16PackedInsts, FeatureBF16TransInsts, FeatureBF8ConversionScaleInsts, + FeatureBVHRayTracingInsts, FeatureBitOp3Insts, FeatureCIInsts, + FeatureClusters, FeatureCubeInsts, FeatureCvtPkNormVOP2Insts, + FeatureCvtPkNormVOP3Insts, FeatureDLInsts, FeatureDPP, + FeatureDot10Insts, FeatureDot11Insts, FeatureDot12Insts, + FeatureDot13Insts, FeatureDot1Insts, FeatureDot2Insts, + FeatureDot3Insts, FeatureDot4Insts, FeatureDot5Insts, + FeatureDot6Insts, FeatureDot7Insts, FeatureDot8Insts, + FeatureDot9Insts, FeatureExtendedImageInsts, FeatureF16BF16ToFP6BF6ConversionScaleInsts, + FeatureF32ToF16BF16ConversionSRInsts, FeatureF32ToFP6BF6ConversionScaleInsts, FeatureFP4ConversionScaleInsts, + FeatureFP6BF6ConversionScaleInsts, FeatureFP8ConversionInsts, FeatureFP8ConversionScaleInsts, + FeatureFP8E5M3Insts, FeatureFP8Insts, FeatureFlatGlobalInsts, + FeatureGFX10Insts, FeatureGFX10_3Insts, FeatureGFX11Insts, + FeatureGFX1250Insts, FeatureGFX1251GEMMInsts, FeatureGFX12Insts, + FeatureGFX13Insts, FeatureGFX8Insts, FeatureGFX90AInsts, + FeatureGFX940Insts, FeatureGFX950Insts, FeatureGFX9Insts, + FeatureGWS, FeatureImageInsts, FeatureLerpInst, + FeatureMAIInsts, FeatureMcastLoadInsts, FeatureMqsadInsts, + FeatureMqsadPkInsts, FeatureMsadInsts, FeaturePermlane16Swap, + FeaturePermlane32Swap, FeaturePkAddMinMaxInsts, FeaturePrngInst, + FeatureQsadInsts, FeatureSMemRealTime, FeatureSMemTimeInst, + FeatureSWMMACGfx1200Insts, FeatureSWMMACGfx1250Insts, FeatureSWakeupBarrier, + FeatureSadInsts, FeatureSetPrioIncWgInst, FeatureSmemPrefetchInsts, + FeatureTanhInsts, FeatureTensorCvtLutInsts, FeatureTransposeLoadF4F6Insts, + FeatureVMemToLDSLoad, FeatureVmemPrefInsts, FeatureWMMA128bInsts, + FeatureWMMA256bInsts, FeatureXF32Insts, + FeatureWavefrontSize32, FeatureWavefrontSize64 + ]; +} + // Include AMDGPU TD files include "SISchedule.td" include "GCNProcessors.td" diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp index 6e16bc8dc9507..61addf60b284c 100644 --- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp +++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp @@ -12,6 +12,7 @@ #include "llvm/TargetParser/AMDGPUTargetParser.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Bitset.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringTable.h" #include "llvm/ADT/Twine.h" @@ -27,6 +28,15 @@ namespace { constexpr unsigned NumAMDGPUSubArches = Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch + 1; +// The frontend-visible SubtargetFeatures, one enumerator per bit in a GPU's +// feature bitset (NUM_FEATURES is the count). +enum AMDGPUFeature : unsigned { +#define GET_AMDGPU_FEATURE_ENUM +#include "llvm/TargetParser/AMDGPUTargetParserDef.inc" +}; + +using AMDGPUFeatureBitset = Bitset<NUM_FEATURES>; + // A legacy GPU name (e.g. "tahiti") mapped to the GPUKind it aliases. struct GPUNameAlias { StringTable::Offset AltName; @@ -38,6 +48,7 @@ struct GPUInfo { StringTable::Offset Name; Triple::SubArchType SubArch; unsigned ArchFeatures; + AMDGPUFeatureBitset Features; IsaVersion Version; StringTable::Offset FamilyName; }; @@ -53,6 +64,7 @@ struct R600Info { #define GET_AMDGPU_GPU_ALIAS_TABLE #define GET_AMDGPU_MAJOR_SUBARCH #define GET_AMDGPU_SUBARCH_NAME +#define GET_AMDGPU_FEATURE_NAME_TABLE #include "llvm/TargetParser/AMDGPUTargetParserDef.inc" #define GET_R600_NAME_TABLE @@ -415,16 +427,40 @@ StringRef AMDGPU::getCanonicalArchName(const Triple &T, StringRef Arch) { return T.isAMDGCN() ? getArchNameAMDGCN(ProcKind) : getArchNameR600(ProcKind); } +// Add each frontend feature in \p Info's bitset to \p Features. With \p +// Overwrite false, existing entries are kept so user -mattr overrides win. +static void addGPUFeatures(const GPUInfo &Info, bool Overwrite, + StringMap<bool> &Features) { + for (unsigned I = 0; I != NUM_FEATURES; ++I) { + if (!Info.Features.test(I)) + continue; + StringRef Name = AMDGPUNameStrTab[AMDGPUFeatureNames[I]]; + if (Overwrite) + Features[Name] = true; + else + Features.insert({Name, true}); + } +} + +/// Add a GPU's default features to \p Features (preserving user overrides) and +/// validate any requested wavesize. static std::pair<FeatureError, StringRef> -insertWaveSizeFeature(StringRef GPU, const Triple &T, - const StringMap<bool> &DefaultFeatures, - StringMap<bool> &Features) { +fillAMDGCNFeatureMap(StringRef GPU, const Triple &T, + StringMap<bool> &Features) { + // With no explicit GPU, the triple's subarch identifies the target. + GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch + ? getGPUKindFromSubArch(T.getSubArch()) + : parseArchAMDGCN(GPU); + const GPUInfo *Info = getAMDGPUInfo(Kind); + // A bare subarch triple (no -target-cpu) still pins down the target, so it is - // not a null GPU: DefaultFeatures has already been populated from the - // subarch. + // not a null GPU. The target's native wavesize (if single-mode) is in the + // feature bitset; a dual-mode GPU has neither wave bit set. const bool IsNullGPU = T.getSubArch() == Triple::NoSubArch && GPU.empty(); - const bool TargetHasWave32 = DefaultFeatures.count("wavefrontsize32"); - const bool TargetHasWave64 = DefaultFeatures.count("wavefrontsize64"); + const bool TargetHasWave32 = + Info && Info->Features.test(FEATURE_WAVEFRONTSIZE32); + const bool TargetHasWave64 = + Info && Info->Features.test(FEATURE_WAVEFRONTSIZE64); auto Wave32Itr = Features.find("wavefrontsize32"); auto Wave64Itr = Features.find("wavefrontsize64"); @@ -464,501 +500,15 @@ insertWaveSizeFeature(StringRef GPU, const Triple &T, // Default to wave32 if target supports both. if (!IsNullGPU && !EnableWave32 && !EnableWave64 && !TargetHasWave32 && !TargetHasWave64) - Features.insert(std::make_pair("wavefrontsize32", true)); + Features.insert({"wavefrontsize32", true}); - for (const auto &Entry : DefaultFeatures) { - if (!Features.count(Entry.getKey())) - Features[Entry.getKey()] = Entry.getValue(); - } + // Merge the target defaults, keeping any user -mattr overrides. + if (Info) + addGPUFeatures(*Info, /*Overwrite=*/false, Features); return {NO_ERROR, StringRef()}; } -/// Fills Features map with default values for given target GPU. -/// \p Features contains overriding target features and this function returns -/// default target features with entries overridden by \p Features. -static void fillAMDGCNFeatureMap(StringRef GPU, const Triple &T, - StringMap<bool> &Features) { - // With no explicit GPU, the triple's subarch identifies the target. - AMDGPU::GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch - ? getGPUKindFromSubArch(T.getSubArch()) - : parseArchAMDGCN(GPU); - switch (Kind) { - case GK_GFX1310: - case GK_GFX13_GENERIC: - Features["ci-insts"] = true; - Features["dot7-insts"] = true; - Features["dot8-insts"] = true; - Features["dl-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["gfx11-insts"] = true; - Features["gfx12-insts"] = true; - Features["gfx1250-insts"] = true; - Features["gfx13-insts"] = true; - Features["bitop3-insts"] = true; - Features["prng-inst"] = true; - Features["tanh-insts"] = true; - Features["tensor-cvt-lut-insts"] = true; - Features["bf16-trans-insts"] = true; - Features["bf16-cvt-insts"] = true; - Features["bf16-pk-insts"] = true; - Features["fp8-conversion-insts"] = true; - Features["permlane16-swap"] = true; - Features["ashr-pk-insts"] = true; - Features["atomic-buffer-pk-add-bf16-inst"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["atomic-buffer-global-pk-add-f16-insts"] = true; - Features["atomic-flat-pk-add-16-insts"] = true; - Features["atomic-global-pk-add-bf16-inst"] = true; - Features["atomic-ds-pk-add-16-insts"] = true; - Features["s-wakeup-barrier-inst"] = true; - Features["f16bf16-to-fp6bf6-cvt-scale-insts"] = true; - Features["f32-to-fp6bf6-cvt-scale-insts"] = true; - Features["clusters"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["cvt-pknorm-vop3-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["async-load-to-lds-insts"] = true; - break; - case GK_GFX1251: - Features["gfx1251-gemm-insts"] = true; - [[fallthrough]]; - case GK_GFX1250: - Features["swmmac-gfx1200-insts"] = true; - Features["swmmac-gfx1250-insts"] = true; - Features["cube-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["lerp-inst"] = true; - Features["qsad-insts"] = true; - Features["sad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - [[fallthrough]]; - case GK_GFX12_5_GENERIC: - Features["ci-insts"] = true; - Features["dot7-insts"] = true; - Features["dot8-insts"] = true; - Features["dl-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["gfx11-insts"] = true; - Features["gfx12-insts"] = true; - Features["gfx1250-insts"] = true; - Features["bitop3-insts"] = true; - Features["prng-inst"] = true; - Features["tanh-insts"] = true; - Features["tensor-cvt-lut-insts"] = true; - Features["transpose-load-f4f6-insts"] = true; - Features["bf16-trans-insts"] = true; - Features["bf16-cvt-insts"] = true; - Features["bf16-pk-insts"] = true; - Features["fp8-conversion-insts"] = true; - Features["fp8e5m3-insts"] = true; - Features["permlane16-swap"] = true; - Features["ashr-pk-insts"] = true; - Features["add-min-max-insts"] = true; - Features["pk-add-min-max-insts"] = true; - Features["atomic-buffer-pk-add-bf16-inst"] = true; - Features["vmem-pref-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["atomic-buffer-global-pk-add-f16-insts"] = true; - Features["atomic-flat-pk-add-16-insts"] = true; - Features["atomic-global-pk-add-bf16-inst"] = true; - Features["atomic-ds-pk-add-16-insts"] = true; - Features["setprio-inc-wg-inst"] = true; - Features["s-wakeup-barrier-inst"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["wavefrontsize32"] = true; - Features["clusters"] = true; - Features["mcast-load-insts"] = true; - Features["async-load-to-lds-insts"] = true; - Features["async-store-from-lds-insts"] = true; - Features["asynccnt"] = true; - break; - case GK_GFX1201: - case GK_GFX1200: - case GK_GFX12_GENERIC: - Features["ci-insts"] = true; - Features["dot7-insts"] = true; - Features["dot8-insts"] = true; - Features["dot9-insts"] = true; - Features["dot10-insts"] = true; - Features["dot11-insts"] = true; - Features["dot12-insts"] = true; - Features["dl-insts"] = true; - Features["atomic-ds-pk-add-16-insts"] = true; - Features["atomic-flat-pk-add-16-insts"] = true; - Features["atomic-buffer-global-pk-add-f16-insts"] = true; - Features["atomic-buffer-pk-add-bf16-inst"] = true; - Features["atomic-global-pk-add-bf16-inst"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["gfx11-insts"] = true; - Features["gfx12-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["bvh-ray-tracing-insts"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["fp8-conversion-insts"] = true; - Features["wmma-128b-insts"] = true; - Features["swmmac-gfx1200-insts"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["smem-prefetch-insts"] = true; - break; - case GK_GFX1170: - case GK_GFX1171: - case GK_GFX1172: - case GK_GFX11_7_GENERIC: - Features["ci-insts"] = true; - Features["dot7-insts"] = true; - Features["dot8-insts"] = true; - Features["dot9-insts"] = true; - Features["dot10-insts"] = true; - Features["dot12-insts"] = true; - Features["dl-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["gfx11-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["bvh-ray-tracing-insts"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["gws"] = true; - Features["dot11-insts"] = true; - Features["fp8-conversion-insts"] = true; - Features["wmma-128b-insts"] = true; - Features["swmmac-gfx1200-insts"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - break; - case GK_GFX1154: - case GK_GFX1153: - case GK_GFX1152: - case GK_GFX1151: - case GK_GFX1150: - case GK_GFX1103: - case GK_GFX1102: - case GK_GFX1101: - case GK_GFX1100: - case GK_GFX11_GENERIC: - Features["ci-insts"] = true; - Features["dot5-insts"] = true; - Features["dot7-insts"] = true; - Features["dot8-insts"] = true; - Features["dot9-insts"] = true; - Features["dot10-insts"] = true; - Features["dot12-insts"] = true; - Features["dl-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["gfx11-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["bvh-ray-tracing-insts"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["gws"] = true; - Features["wmma-256b-insts"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - break; - case GK_GFX1036: - case GK_GFX1035: - case GK_GFX1034: - case GK_GFX1033: - case GK_GFX1032: - case GK_GFX1031: - case GK_GFX1030: - case GK_GFX10_3_GENERIC: - Features["ci-insts"] = true; - Features["dot1-insts"] = true; - Features["dot2-insts"] = true; - Features["dot5-insts"] = true; - Features["dot6-insts"] = true; - Features["dot7-insts"] = true; - Features["dot10-insts"] = true; - Features["dl-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["gfx10-3-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["bvh-ray-tracing-insts"] = true; - Features["s-memrealtime"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["vmem-to-lds-load-insts"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - break; - case GK_GFX1012: - case GK_GFX1011: - Features["dot1-insts"] = true; - Features["dot2-insts"] = true; - Features["dot5-insts"] = true; - Features["dot6-insts"] = true; - Features["dot7-insts"] = true; - Features["dot10-insts"] = true; - [[fallthrough]]; - case GK_GFX1013: - case GK_GFX1010: - case GK_GFX10_1_GENERIC: - if (Kind == GK_GFX1013) - Features["bvh-ray-tracing-insts"] = true; - Features["dl-insts"] = true; - Features["ci-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["gfx8-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx10-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["s-memrealtime"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["vmem-to-lds-load-insts"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - break; - case GK_GFX950: - Features["bitop3-insts"] = true; - Features["fp6bf6-cvt-scale-insts"] = true; - Features["fp4-cvt-scale-insts"] = true; - Features["bf8-cvt-scale-insts"] = true; - Features["fp8-cvt-scale-insts"] = true; - Features["f16bf16-to-fp6bf6-cvt-scale-insts"] = true; - Features["f32-to-f16bf16-cvt-sr-insts"] = true; - Features["prng-inst"] = true; - Features["permlane16-swap"] = true; - Features["permlane32-swap"] = true; - Features["ashr-pk-insts"] = true; - Features["dot12-insts"] = true; - Features["dot13-insts"] = true; - Features["atomic-buffer-pk-add-bf16-inst"] = true; - Features["gfx950-insts"] = true; - [[fallthrough]]; - case GK_GFX942: - Features["fp8-insts"] = true; - Features["fp8-conversion-insts"] = true; - if (Kind != GK_GFX950) - Features["xf32-insts"] = true; - [[fallthrough]]; - case GK_GFX9_4_GENERIC: - Features["gfx940-insts"] = true; - Features["atomic-ds-pk-add-16-insts"] = true; - Features["atomic-flat-pk-add-16-insts"] = true; - Features["atomic-global-pk-add-bf16-inst"] = true; - Features["gfx90a-insts"] = true; - Features["atomic-buffer-global-pk-add-f16-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["dot3-insts"] = true; - Features["dot4-insts"] = true; - Features["dot5-insts"] = true; - Features["dot6-insts"] = true; - Features["mai-insts"] = true; - Features["dl-insts"] = true; - Features["dot1-insts"] = true; - Features["dot2-insts"] = true; - Features["dot7-insts"] = true; - Features["dot10-insts"] = true; - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["gfx8-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["s-memrealtime"] = true; - Features["ci-insts"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["vmem-to-lds-load-insts"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["wavefrontsize64"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - break; - case GK_GFX90A: - Features["gfx90a-insts"] = true; - Features["atomic-buffer-global-pk-add-f16-insts"] = true; - Features["atomic-fadd-rtn-insts"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - [[fallthrough]]; - case GK_GFX908: - Features["dot3-insts"] = true; - Features["dot4-insts"] = true; - Features["dot5-insts"] = true; - Features["dot6-insts"] = true; - Features["mai-insts"] = true; - [[fallthrough]]; - case GK_GFX906: - Features["dl-insts"] = true; - Features["dot1-insts"] = true; - Features["dot2-insts"] = true; - Features["dot7-insts"] = true; - Features["dot10-insts"] = true; - [[fallthrough]]; - case GK_GFX90C: - case GK_GFX909: - case GK_GFX904: - case GK_GFX902: - case GK_GFX900: - case GK_GFX9_GENERIC: - Features["gfx9-insts"] = true; - Features["flat-global-insts"] = true; - Features["vmem-to-lds-load-insts"] = true; - [[fallthrough]]; - case GK_GFX810: - case GK_GFX805: - case GK_GFX803: - case GK_GFX802: - case GK_GFX801: - Features["gfx8-insts"] = true; - Features["16-bit-insts"] = true; - Features["dpp"] = true; - Features["s-memrealtime"] = true; - Features["ci-insts"] = true; - Features["image-insts"] = true; - if (Kind != GK_GFX90A) - Features["extended-image-insts"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["wavefrontsize64"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - break; - case GK_GFX705: - case GK_GFX704: - case GK_GFX703: - case GK_GFX702: - case GK_GFX701: - case GK_GFX700: - Features["ci-insts"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["qsad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["mqsad-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["wavefrontsize64"] = true; - break; - case GK_GFX602: - case GK_GFX601: - case GK_GFX600: - Features["image-insts"] = true; - Features["extended-image-insts"] = true; - Features["s-memtime-inst"] = true; - Features["gws"] = true; - Features["atomic-fmin-fmax-global-f32"] = true; - Features["atomic-fmin-fmax-global-f64"] = true; - Features["wavefrontsize64"] = true; - Features["cube-insts"] = true; - Features["lerp-inst"] = true; - Features["sad-insts"] = true; - Features["msad-insts"] = true; - Features["mqsad-pk-insts"] = true; - Features["cvt-pknorm-vop2-insts"] = true; - break; - case GK_NONE: - break; - default: - llvm_unreachable("Unhandled GPU!"); - } -} - /// Fills Features map with default values for given target GPU. /// \p Features contains overriding target features and this function returns /// default target features with entries overridden by \p Features. @@ -970,20 +520,13 @@ AMDGPU::fillAMDGPUFeatureMap(StringRef GPU, const Triple &T, // AMDGCN SPIRV must support the union of all AMDGCN features. SmallVector<StringRef> GPUs; fillValidArchListAMDGCN(GPUs); - - static const Triple AMDGCN("amdgcn-amd-amdhsa"); - StringMap<bool> Tmp; - for (auto &&GPU : GPUs) { - fillAMDGCNFeatureMap(GPU, AMDGCN, Tmp); - for (auto &&[F, B] : Tmp) - Features[F] = B; - } + for (StringRef G : GPUs) + if (const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(G))) + addGPUFeatures(*Info, /*Overwrite=*/true, Features); Features["wavefrontsize32"] = true; Features["wavefrontsize64"] = true; } else if (T.isAMDGCN()) { - StringMap<bool> DefaultFeatures; - fillAMDGCNFeatureMap(GPU, T, DefaultFeatures); - return insertWaveSizeFeature(GPU, T, DefaultFeatures, Features); + return fillAMDGCNFeatureMap(GPU, T, Features); } else { if (GPU.empty()) GPU = "r600"; diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index e28392fc25195..b55b1428534ab 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -2746,6 +2746,49 @@ TEST(TargetParserTest, testAMDGPUparseArchR600) { EXPECT_TRUE(llvm::is_contained(Values, A.Alias)) << A.Alias; } +TEST(TargetParserTest, testAMDGPUfillAMDGPUFeatureMap) { + auto HasFeature = [](StringRef GPU, StringRef Feature) { + StringMap<bool> Features; + AMDGPU::fillAMDGPUFeatureMap(GPU, Triple("amdgcn-amd-amdhsa"), Features); + auto It = Features.find(Feature); + return It != Features.end() && It->second; + }; + + // Instruction features come from the .td SubtargetFeature closure, so a GPU + // gets everything its features transitively imply (not a hand-maintained + // subset). gfx900 implies the gfx8/gfx9 instruction sets. + EXPECT_TRUE(HasFeature("gfx900", "gfx9-insts")); + EXPECT_TRUE(HasFeature("gfx900", "gfx8-insts")); + EXPECT_TRUE(HasFeature("gfx900", "ci-insts")); + EXPECT_TRUE(HasFeature("gfx900", "dpp")); + // cvt-pknorm-vop3-insts is implied by FeatureGFX9 alongside the vop2 variant. + EXPECT_TRUE(HasFeature("gfx900", "cvt-pknorm-vop2-insts")); + EXPECT_TRUE(HasFeature("gfx900", "cvt-pknorm-vop3-insts")); + // extended-image-insts is available on gfx6-gfx11/gfx13 hardware. + EXPECT_TRUE(HasFeature("gfx900", "extended-image-insts")); + EXPECT_TRUE(HasFeature("gfx1100", "extended-image-insts")); + + // Backend-only features are not frontend-visible. + EXPECT_FALSE(HasFeature("gfx900", "flat-scratch-insts")); + EXPECT_FALSE(HasFeature("gfx900", "sdwa")); + + // Native wavesize: wave64-only GPUs pin wavefrontsize64 and wave32-only GPUs + // pin wavefrontsize32 (from the feature closure). Dual-mode GPUs + // (gfx10/gfx11) carry neither in the closure, so insertWaveSizeFeature + // defaults them to wavefrontsize32. + EXPECT_TRUE(HasFeature("gfx900", "wavefrontsize64")); + EXPECT_FALSE(HasFeature("gfx900", "wavefrontsize32")); + EXPECT_TRUE(HasFeature("gfx1250", "wavefrontsize32")); + EXPECT_FALSE(HasFeature("gfx1250", "wavefrontsize64")); + EXPECT_TRUE(HasFeature("gfx1010", "wavefrontsize32")); + EXPECT_FALSE(HasFeature("gfx1010", "wavefrontsize64")); + + // gfx1250/gfx1310 newer features. + EXPECT_TRUE(HasFeature("gfx1250", "bvh-ray-tracing-insts")); + EXPECT_TRUE(HasFeature("gfx1250", "smem-prefetch-insts")); + EXPECT_TRUE(HasFeature("gfx950", "bf16-cvt-insts")); +} + TEST(TargetParserTest, testAMDGPUfillValidArchListAMDGCN) { SmallVector<StringRef, 0> All; AMDGPU::fillValidArchListAMDGCN(All, Triple::NoSubArch); diff --git a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp index b303a415521cb..4c54cae565a9a 100644 --- a/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/Basic/AMDGPUTargetDefEmitter.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -34,6 +36,13 @@ static void emitGPUKindEnum(raw_ostream &OS, StringRef Name) { OS << ((C == '-') ? '_' : toUpper(C)); } +// Feature string to enumerator, e.g. "16-bit-insts" -> "FEATURE_16_BIT_INSTS". +static void emitFeatureEnum(raw_ostream &OS, StringRef Name) { + OS << "FEATURE_"; + for (char C : Name) + OS << ((C == '-') ? '_' : toUpper(C)); +} + // Emit the Triple::AMDGPUSubArch enumerator suffix for a "gfx..." GPU name, // e.g. "gfx90a" -> "90A", "gfx9-generic" -> "9" (the family major). static void emitSubArchSuffix(raw_ostream &OS, StringRef Name) { @@ -153,6 +162,29 @@ static void emitFeatureExpr(raw_ostream &OS, const Record *Rec, OS << NoneSpelling; } +// The frontend-visible features, bit order matching the list. Empty for R600 +// (no AMDGPUFrontendVisibleFeatures def). +static std::vector<const Record *> +collectFrontendFeatures(const RecordKeeper &RK) { + const Record *List = RK.getDef("AMDGPUFrontendVisibleFeatures"); + if (!List) + return {}; + return List->getValueAsListOfDefs("Features"); +} + +// The transitive closure of a GPU's SubtargetFeatures, following the Implies +// edges (a feature enables everything it implies). +static void collectFeatureClosure(const Record *GPU, + SetVector<const Record *> &Closure) { + std::vector<const Record *> Worklist = GPU->getValueAsListOfDefs("Features"); + while (!Worklist.empty()) { + const Record *F = Worklist.back(); + Worklist.pop_back(); + if (Closure.insert(F)) + append_range(Worklist, F->getValueAsListOfDefs("Implies")); + } +} + // Collect canonical GPUs and their aliases, in TableGen definition order. R600 // GPUs are plain Processor records; AMDGPU GPUs are ProcessorModel records (a // Processor subclass), so \p WantR600 selects the family to emit. @@ -350,10 +382,77 @@ static void emitAMDGPUAliases(raw_ostream &OS, const RecordKeeper &RK, "#endif // GET_AMDGPU_GPU_ALIAS_TABLE\n\n"; } +// Emit the frontend feature enum (GET_AMDGPU_FEATURE_ENUM), interning each +// feature name into \p Names. Returns the name offsets indexed by feature bit. +static std::vector<unsigned> +emitAMDGPUFeatureEnum(raw_ostream &OS, ArrayRef<const Record *> Features, + StringToOffsetTable &Names) { + std::vector<unsigned> Offsets; + if (Features.empty()) + return Offsets; + Offsets.reserve(Features.size()); + + OS << "#ifdef GET_AMDGPU_FEATURE_ENUM\n" + "#undef GET_AMDGPU_FEATURE_ENUM\n"; + for (const Record *F : Features) { + StringRef Name = F->getValueAsString("Name"); + OS << " "; + emitFeatureEnum(OS, Name); + OS << ",\n"; + Offsets.push_back(Names.GetOrAddStringOffset(Name)); + } + OS << " NUM_FEATURES\n" + "#endif // GET_AMDGPU_FEATURE_ENUM\n\n"; + return Offsets; +} + +// Emit AMDGPUFeatureNames (GET_AMDGPU_FEATURE_NAME_TABLE): bit -> name offset. +static void emitAMDGPUFeatureNames(raw_ostream &OS, + ArrayRef<unsigned> Offsets) { + if (Offsets.empty()) + return; + OS << "#ifdef GET_AMDGPU_FEATURE_NAME_TABLE\n" + "#undef GET_AMDGPU_FEATURE_NAME_TABLE\n" + "static constexpr StringTable::Offset AMDGPUFeatureNames[] = {\n"; + for (unsigned O : Offsets) + OS << " " << O << ",\n"; + OS << "};\n" + "#endif // GET_AMDGPU_FEATURE_NAME_TABLE\n\n"; +} + +// Emit a GPU's feature bitset initializer: its feature closure intersected with +// the frontend-visible set \p FeatureIdx, e.g. +// "AMDGPUFeatureBitset({FEATURE_DPP, FEATURE_CI_INSTS})". +static void +emitFeatureBitset(raw_ostream &OS, const Record *GPU, + const DenseMap<const Record *, unsigned> &FeatureIdx) { + SetVector<const Record *> Closure; + collectFeatureClosure(GPU, Closure); + + // Sort by bit index for stable output. + SmallVector<std::pair<unsigned, StringRef>> Bits; + for (const Record *F : Closure) { + auto It = FeatureIdx.find(F); + if (It != FeatureIdx.end()) + Bits.emplace_back(It->second, F->getValueAsString("Name")); + } + sort(Bits); + + OS << "AMDGPUFeatureBitset({"; + ListSeparator LS(", "); + for (const auto &[Idx, Name] : Bits) { + OS << LS; + emitFeatureEnum(OS, Name); + } + OS << "})"; +} + /// Emit a GPUInfo table indexed by (GPUKind - AMDGPUFirstGPUKind). Name and /// family strings are stored as offsets into the shared \p Names table. -static void emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK, - StringToOffsetTable &Names) { +static void +emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK, + StringToOffsetTable &Names, + const DenseMap<const Record *, unsigned> &FeatureIdx) { std::vector<const Record *> Canon = collectAMDGPUCanonicals(RK); if (Canon.empty()) return; @@ -371,6 +470,8 @@ static void emitAMDGPUTable(raw_ostream &OS, const RecordKeeper &RK, OS << ", "; emitFeatureExpr(OS, R, "FEATURE_NONE"); OS << ", "; + emitFeatureBitset(OS, R, FeatureIdx); + OS << ", "; emitIsaVersion(OS, R, '{', '}'); OS << ", " << Names.GetOrAddStringOffset(getArchFamily(R)) << "},\n"; } @@ -536,7 +637,18 @@ static void emitAMDGPUTargetDef(const RecordKeeper &RK, raw_ostream &OS) { StringToOffsetTable Names; std::string Tables; raw_string_ostream TablesOS(Tables); - emitAMDGPUTable(TablesOS, RK, Names); + + // The frontend feature enum and per-GPU bitsets share the AMDGPU string + // pool (feature names live alongside GPU names). + std::vector<const Record *> Features = collectFrontendFeatures(RK); + DenseMap<const Record *, unsigned> FeatureIdx; + for (const auto &[Idx, F] : enumerate(Features)) + FeatureIdx[F] = Idx; + + std::vector<unsigned> FeatureOffsets = + emitAMDGPUFeatureEnum(TablesOS, Features, Names); + emitAMDGPUTable(TablesOS, RK, Names, FeatureIdx); + emitAMDGPUFeatureNames(TablesOS, FeatureOffsets); emitAMDGPUAliases(TablesOS, RK, Names); emitAMDGPUSubArchNames(TablesOS, RK, Names); if (!Tables.empty()) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
