[llvm-branch-commits] [llvm] AMDGPU: Export the TargetParser feature bitset (PR #212946)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jul 30 02:34:16 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/212946

>From 551f3c8548cfb1023e19b7bb9a63713a07ab8fb0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 29 Jul 2026 00:16:17 +0200
Subject: [PATCH] AMDGPU: Export the TargetParser feature bitset

Previously this bitset was only used to populate the feature
name string map used by clang. Eventually this will replace
the current bitmask integer. AArch64 already has a similar
interface.

Co-authored-by: Claude (Claude-Opus-4.8)
---
 .../llvm/TargetParser/AMDGPUTargetParser.h    | 16 ++++++++++
 llvm/lib/TargetParser/AMDGPUTargetParser.cpp  | 31 ++++++++++---------
 .../TargetParser/TargetParserTest.cpp         | 29 +++++++++++++++++
 3 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index fd0072c89be23..765a8baa37012 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_TARGETPARSER_AMDGPUTARGETPARSER_H
 #define LLVM_TARGETPARSER_AMDGPUTARGETPARSER_H
 
+#include "llvm/ADT/Bitset.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -42,6 +43,14 @@ enum GPUKind : uint32_t {
 #include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
 };
 
+/// One enumerator per frontend-visible feature bit; NUM_FEATURES is the count.
+enum AMDGPUFeature : unsigned {
+#define GET_AMDGPU_FEATURE_ENUM
+#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
+};
+
+using AMDGPUFeatureBitset = Bitset<NUM_FEATURES>;
+
 /// Instruction set architecture version.
 struct IsaVersion {
   uint8_t Major;
@@ -156,6 +165,13 @@ LLVM_ABI unsigned getArchAttrAMDGCN(GPUKind AK);
 LLVM_ABI unsigned getArchAttrAMDGCN(Triple::SubArchType SubArch);
 LLVM_ABI R600FeatureKind getArchAttrR600(GPUKind AK);
 
+/// Returns \p AK's feature bitset, or an empty bitset if unknown.
+LLVM_ABI const AMDGPUFeatureBitset &getFeatureBitset(GPUKind AK);
+
+/// Appends the feature name of each bit set in \p Features to \p Names.
+LLVM_ABI void getFeatureNames(const AMDGPUFeatureBitset &Features,
+                              SmallVectorImpl<StringRef> &Names);
+
 /// Append the valid AMDGCN GPU names to \p Values. If \p SubArch is not
 /// NoSubArch, only GPUs compatible with that subarch (see isCPUValidForSubArch)
 /// are appended.
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index 61addf60b284c..20b03b5247137 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -12,7 +12,6 @@
 
 #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"
@@ -28,15 +27,6 @@ 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;
@@ -328,6 +318,20 @@ R600FeatureKind AMDGPU::getArchAttrR600(GPUKind AK) {
   return Info ? Info->ArchFeatures : R600_FEATURE_NONE;
 }
 
+const AMDGPUFeatureBitset &AMDGPU::getFeatureBitset(GPUKind AK) {
+  static constexpr AMDGPUFeatureBitset Empty{};
+  const GPUInfo *Info = getAMDGPUInfo(AK);
+  return Info ? Info->Features : Empty;
+}
+
+void AMDGPU::getFeatureNames(const AMDGPUFeatureBitset &Features,
+                             SmallVectorImpl<StringRef> &Names) {
+  for (unsigned I = 0; I != NUM_FEATURES; ++I) {
+    if (Features.test(I))
+      Names.push_back(AMDGPUNameStrTab[AMDGPUFeatureNames[I]]);
+  }
+}
+
 void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values,
                                      Triple::SubArchType SubArch) {
   // XXX: Should this only report unique canonical names?
@@ -431,10 +435,9 @@ StringRef AMDGPU::getCanonicalArchName(const Triple &T, StringRef Arch) {
 // 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]];
+  SmallVector<StringRef, NUM_FEATURES> Names;
+  getFeatureNames(Info.Features, Names);
+  for (StringRef Name : Names) {
     if (Overwrite)
       Features[Name] = true;
     else
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index b55b1428534ab..b19050ff9fc39 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -2789,6 +2789,35 @@ TEST(TargetParserTest, testAMDGPUfillAMDGPUFeatureMap) {
   EXPECT_TRUE(HasFeature("gfx950", "bf16-cvt-insts"));
 }
 
+TEST(TargetParserTest, testAMDGPUgetFeatureBitset) {
+  // getFeatureBitset exposes the same per-GPU frontend feature set that
+  // fillAMDGPUFeatureMap consumes internally.
+  const AMDGPU::AMDGPUFeatureBitset &GFX900 =
+      AMDGPU::getFeatureBitset(AMDGPU::GK_GFX900);
+  EXPECT_TRUE(GFX900.test(AMDGPU::FEATURE_GFX9_INSTS));
+  EXPECT_TRUE(GFX900.test(AMDGPU::FEATURE_GFX8_INSTS));
+  EXPECT_TRUE(GFX900.test(AMDGPU::FEATURE_DPP));
+  EXPECT_TRUE(GFX900.test(AMDGPU::FEATURE_WAVEFRONTSIZE64));
+  EXPECT_FALSE(GFX900.test(AMDGPU::FEATURE_WAVEFRONTSIZE32));
+
+  // An unknown kind yields an empty bitset.
+  EXPECT_EQ(AMDGPU::getFeatureBitset(AMDGPU::GK_NONE).count(), 0u);
+
+  // getFeatureNames maps the set bits back to their SubtargetFeature names, one
+  // per set bit.
+  SmallVector<StringRef, 0> Names;
+  AMDGPU::getFeatureNames(GFX900, Names);
+  EXPECT_EQ(Names.size(), GFX900.count());
+  EXPECT_NE(llvm::find(Names, "gfx9-insts"), Names.end());
+  EXPECT_NE(llvm::find(Names, "dpp"), Names.end());
+  EXPECT_NE(llvm::find(Names, "wavefrontsize64"), Names.end());
+  EXPECT_EQ(llvm::find(Names, "wavefrontsize32"), Names.end());
+
+  SmallVector<StringRef, 0> Empty;
+  AMDGPU::getFeatureNames(AMDGPU::getFeatureBitset(AMDGPU::GK_NONE), Empty);
+  EXPECT_TRUE(Empty.empty());
+}
+
 TEST(TargetParserTest, testAMDGPUfillValidArchListAMDGCN) {
   SmallVector<StringRef, 0> All;
   AMDGPU::fillValidArchListAMDGCN(All, Triple::NoSubArch);



More information about the llvm-branch-commits mailing list