[clang] 3c3a18e - clang: Store vendor GPU kinds in OffloadArch instead of re-listing GPUs (#213362)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 31 23:14:10 PDT 2026
Author: Matt Arsenault
Date: 2026-08-01T06:14:04Z
New Revision: 3c3a18e239fcb79ad780cc95ac7554046876da2a
URL: https://github.com/llvm/llvm-project/commit/3c3a18e239fcb79ad780cc95ac7554046876da2a
DIFF: https://github.com/llvm/llvm-project/commit/3c3a18e239fcb79ad780cc95ac7554046876da2a.diff
LOG: clang: Store vendor GPU kinds in OffloadArch instead of re-listing GPUs (#213362)
OffloadArch was a flat enum that hand-duplicated every AMDGPU and NVPTX
target, plus a few edge cases. This was yet another place that needed
updating every time a new target is added, which should now be avoided.
Replace with a tagged union-like scheme.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
Added:
Modified:
clang/include/clang/Basic/OffloadArch.h
clang/include/clang/Driver/CudaInstallationDetector.h
clang/lib/Basic/Cuda.cpp
clang/lib/Basic/OffloadArch.cpp
clang/lib/Basic/Targets/NVPTX.cpp
clang/lib/Basic/Targets/NVPTX.h
clang/lib/Driver/Driver.cpp
clang/lib/Driver/OffloadBundler.cpp
clang/lib/Driver/ToolChains/Cuda.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/Misc/target-invalid-cpu-note/nvptx.c
clang/unittests/Basic/OffloadArchTest.cpp
llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
llvm/include/llvm/TargetParser/NVPTXTargetParser.h
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/OffloadArch.h b/clang/include/clang/Basic/OffloadArch.h
index 552f1b0316ccf..069352ea37f89 100644
--- a/clang/include/clang/Basic/OffloadArch.h
+++ b/clang/include/clang/Basic/OffloadArch.h
@@ -10,161 +10,121 @@
#define LLVM_CLANG_BASIC_OFFLOADARCH_H
#include "llvm/ADT/StringRef.h"
+#include <cstdint>
#include <tuple>
namespace llvm {
class Triple;
+template <typename T> class SmallVectorImpl;
+namespace NVPTX {
+enum GPUKind : uint8_t;
+}
+namespace AMDGPU {
+enum GPUKind : uint8_t;
+}
} // namespace llvm
namespace clang {
-enum class OffloadArch {
- Unused,
- Unknown,
- // TODO: Deprecate and remove GPU architectures older than sm_52.
- SM_20,
- SM_21,
- SM_30,
- // This has a name conflict with sys/mac.h on AIX, rename it as a workaround.
- SM_32_,
- SM_35,
- SM_37,
- SM_50,
- SM_52,
- SM_53,
- SM_60,
- SM_61,
- SM_62,
- SM_70,
- SM_72,
- SM_75,
- SM_80,
- SM_86,
- SM_87,
- SM_88,
- SM_89,
- SM_90,
- SM_90a,
- SM_100,
- SM_100a,
- SM_100f,
- SM_101,
- SM_101a,
- SM_101f,
- SM_103,
- SM_103a,
- SM_103f,
- SM_110,
- SM_110a,
- SM_110f,
- SM_120,
- SM_120a,
- SM_120f,
- SM_121,
- SM_121a,
- SM_121f,
- GFX600,
- GFX601,
- GFX602,
- GFX700,
- GFX701,
- GFX702,
- GFX703,
- GFX704,
- GFX705,
- GFX801,
- GFX802,
- GFX803,
- GFX805,
- GFX810,
- GFX9_GENERIC,
- GFX900,
- GFX902,
- GFX904,
- GFX906,
- GFX908,
- GFX909,
- GFX90a,
- GFX90c,
- GFX9_4_GENERIC,
- GFX942,
- GFX950,
- GFX10_1_GENERIC,
- GFX1010,
- GFX1011,
- GFX1012,
- GFX1013,
- GFX10_3_GENERIC,
- GFX1030,
- GFX1031,
- GFX1032,
- GFX1033,
- GFX1034,
- GFX1035,
- GFX1036,
- GFX11_GENERIC,
- GFX1100,
- GFX1101,
- GFX1102,
- GFX1103,
- GFX1150,
- GFX1151,
- GFX1152,
- GFX1153,
- GFX1154,
- GFX11_7_GENERIC,
- GFX1170,
- GFX1171,
- GFX1172,
- GFX12_GENERIC,
- GFX1200,
- GFX1201,
- GFX12_5_GENERIC,
- GFX1250,
- GFX1251,
- GFX13_GENERIC,
- GFX1310,
- AMDGCNSPIRV,
- Generic, // A processor model named 'generic' if the target backend defines a
- // public one.
- // Intel CPUs
- GRANITERAPIDS,
- // Intel GPUs
- BMG_G21,
- LAST = BMG_G21,
-
- CudaDefault = OffloadArch::SM_52,
- HIPDefault = OffloadArch::GFX906,
-};
-
-static inline bool IsNVIDIAOffloadArch(OffloadArch A) {
- return A >= OffloadArch::SM_20 && A < OffloadArch::GFX600;
-}
-
-static inline bool IsAMDOffloadArch(OffloadArch A) {
- // Generic processor model is for testing only.
- return A >= OffloadArch::GFX600 && A < OffloadArch::Generic;
-}
+/// A processor an offloading action can target. This is a tagged handle pairing
+/// a TargetArch with the matching TargetParser GPU kind; it does not enumerate
+/// individual GPUs, so new targets are added in the TargetParser data alone.
+class OffloadArch {
+public:
+ enum class TargetArch : uint8_t {
+ Unused, // Default-constructed; no architecture bound.
+ Unknown, // A name that matched no known architecture.
+ NVPTX, // Kind is an llvm::NVPTX::GPUKind.
+ AMDGPU, // Kind is an llvm::AMDGPU::GPUKind.
+ SPIRV, // The 'amdgcnspirv' pseudo target.
+ IntelCPU, // Kind is an IntelArch.
+ IntelGPU, // Kind is an IntelArch.
+ Generic, // The 'generic' processor model.
+ };
+
+ // Intel architectures, which have no TargetParser list yet.
+ enum class IntelArch : uint32_t {
+ GRANITERAPIDS,
+ BMG_G21,
+ };
+
+private:
+ // Interpreted according to V; unused for the tagless TargetArch values.
+ uint32_t Kind = 0;
+ TargetArch V = TargetArch::Unused;
+
+ constexpr OffloadArch(TargetArch V, uint32_t Kind) : Kind(Kind), V(V) {}
+
+public:
+ constexpr OffloadArch() = default;
+
+ static OffloadArch getNVPTX(llvm::NVPTX::GPUKind K) {
+ return {TargetArch::NVPTX, static_cast<uint32_t>(K)};
+ }
+ static OffloadArch getAMDGPU(llvm::AMDGPU::GPUKind K) {
+ return {TargetArch::AMDGPU, static_cast<uint32_t>(K)};
+ }
+ static constexpr OffloadArch getIntel(TargetArch V, IntelArch A) {
+ return {V, static_cast<uint32_t>(A)};
+ }
+ static constexpr OffloadArch getUnused() { return {TargetArch::Unused, 0}; }
+ static constexpr OffloadArch getUnknown() { return {TargetArch::Unknown, 0}; }
+ static constexpr OffloadArch getSPIRV() { return {TargetArch::SPIRV, 0}; }
+ static constexpr OffloadArch getGeneric() { return {TargetArch::Generic, 0}; }
+
+ /// Default architectures used when the user does not specify one.
+ static OffloadArch CudaDefault();
+ static OffloadArch HIPDefault();
+
+ TargetArch targetArch() const { return V; }
+
+ bool isNVPTX() const { return V == TargetArch::NVPTX; }
+ bool isAMDGPU() const { return V == TargetArch::AMDGPU; }
+ bool isSPIRV() const { return V == TargetArch::SPIRV; }
+ bool isIntelCPU() const { return V == TargetArch::IntelCPU; }
+ bool isIntelGPU() const { return V == TargetArch::IntelGPU; }
+ bool isIntel() const { return isIntelCPU() || isIntelGPU(); }
+ bool isGeneric() const { return V == TargetArch::Generic; }
+ bool isUnused() const { return V == TargetArch::Unused; }
+ bool isUnknown() const { return V == TargetArch::Unknown; }
+
+ // Only valid when isNVPTX() / isAMDGPU() respectively.
+ llvm::NVPTX::GPUKind nvptxKind() const {
+ return static_cast<llvm::NVPTX::GPUKind>(Kind);
+ }
+ llvm::AMDGPU::GPUKind amdgpuKind() const {
+ return static_cast<llvm::AMDGPU::GPUKind>(Kind);
+ }
-static inline bool IsIntelCPUOffloadArch(OffloadArch Arch) {
- return Arch >= OffloadArch::GRANITERAPIDS && Arch < OffloadArch::BMG_G21;
-}
+ bool operator==(const OffloadArch &Other) const {
+ return V == Other.V && Kind == Other.Kind;
+ }
+ bool operator!=(const OffloadArch &Other) const { return !(*this == Other); }
-static inline bool IsIntelGPUOffloadArch(OffloadArch Arch) {
- return Arch >= OffloadArch::BMG_G21 && Arch <= OffloadArch::LAST;
-}
+ bool operator<(const OffloadArch &Other) const {
+ return std::tie(V, Kind) < std::tie(Other.V, Other.Kind);
+ }
+};
-static inline bool IsIntelOffloadArch(OffloadArch Arch) {
- return IsIntelCPUOffloadArch(Arch) || IsIntelGPUOffloadArch(Arch);
+inline bool IsNVIDIAOffloadArch(OffloadArch A) { return A.isNVPTX(); }
+inline bool IsAMDOffloadArch(OffloadArch A) {
+ // amdgcnspirv is compiled through the AMDGPU toolchain.
+ return A.isAMDGPU() || A.isSPIRV();
}
+inline bool IsIntelCPUOffloadArch(OffloadArch A) { return A.isIntelCPU(); }
+inline bool IsIntelGPUOffloadArch(OffloadArch A) { return A.isIntelGPU(); }
+inline bool IsIntelOffloadArch(OffloadArch A) { return A.isIntel(); }
const char *OffloadArchToString(OffloadArch A);
const char *OffloadArchToVirtualArchString(OffloadArch A);
-// Convert a string to an OffloadArch enum value. Returns
-// OffloadArch::Unknown if the string is not recognized.
+// Convert a string to an OffloadArch. Returns an Unknown OffloadArch if the
+// string is not recognized.
OffloadArch StringToOffloadArch(llvm::StringRef S);
+/// Append the canonical names of all NVIDIA and AMDGPU GPUs.
+void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values);
+
llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
OffloadArch ID);
@@ -173,19 +133,19 @@ llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
struct BoundArch {
llvm::StringRef ArchName;
- /// The parsed offload architecture enum.
- /// Will be OffloadArch::Unknown if ArchName not recognized.
- OffloadArch Arch = OffloadArch::Unused;
+ /// The parsed offload architecture.
+ /// Will be an Unknown OffloadArch if ArchName is not recognized.
+ OffloadArch Arch = OffloadArch::getUnused();
BoundArch() = default;
explicit BoundArch(llvm::StringRef Name)
- : ArchName(Name),
- Arch(Name.empty() ? OffloadArch::Unknown : StringToOffloadArch(Name)) {}
+ : ArchName(Name), Arch(Name.empty() ? OffloadArch::getUnknown()
+ : StringToOffloadArch(Name)) {}
BoundArch(llvm::StringRef Name, OffloadArch A) : ArchName(Name), Arch(A) {}
bool empty() const { return ArchName.empty(); }
- explicit operator bool() const { return Arch != OffloadArch::Unused; }
+ explicit operator bool() const { return !Arch.isUnused(); }
bool operator==(const BoundArch &Other) const {
return Arch == Other.Arch && ArchName == Other.ArchName;
diff --git a/clang/include/clang/Driver/CudaInstallationDetector.h b/clang/include/clang/Driver/CudaInstallationDetector.h
index 0fecbfe069ca4..98abec7d924bb 100644
--- a/clang/include/clang/Driver/CudaInstallationDetector.h
+++ b/clang/include/clang/Driver/CudaInstallationDetector.h
@@ -11,6 +11,7 @@
#include "clang/Basic/Cuda.h"
#include "clang/Driver/Driver.h"
+#include "llvm/TargetParser/NVPTXTargetParser.h"
#include <bitset>
namespace clang {
@@ -28,9 +29,9 @@ class CudaInstallationDetector {
std::string IncludePath;
llvm::StringMap<std::string> LibDeviceMap;
- // CUDA architectures for which we have raised an error in
- // CheckCudaVersionSupportsArch.
- mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion;
+ // NVIDIA architectures (indexed by GPUKind) for which we have raised an error
+ // in CheckCudaVersionSupportsArch.
+ mutable std::bitset<llvm::NVPTX::GK_LAST + 1> ArchsWithBadVersion;
public:
CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp
index b61d890e23dfe..06c02bd541df3 100644
--- a/clang/lib/Basic/Cuda.cpp
+++ b/clang/lib/Basic/Cuda.cpp
@@ -4,6 +4,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/TargetParser/NVPTXTargetParser.h"
+#include <cassert>
namespace clang {
@@ -78,16 +79,16 @@ CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
}
CudaVersion MinVersionForOffloadArch(OffloadArch A) {
- if (A == OffloadArch::Unknown)
+ if (A.isUnknown())
return CudaVersion::UNKNOWN;
// AMD GPUs do not depend on CUDA versions.
if (IsAMDOffloadArch(A))
return CudaVersion::CUDA_70;
- switch (A) {
+ switch (A.nvptxKind()) {
#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
- case OffloadArch::KIND: \
+ case llvm::NVPTX::GK_##KIND: \
return CudaVersion::MIN_VER;
#include "llvm/TargetParser/NVPTXTargetParser.def"
default:
@@ -100,11 +101,12 @@ CudaVersion MaxVersionForOffloadArch(OffloadArch A) {
if (IsAMDOffloadArch(A))
return CudaVersion::NEW;
- switch (A) {
- case OffloadArch::Unknown:
+ if (!A.isNVPTX())
return CudaVersion::UNKNOWN;
+
+ switch (A.nvptxKind()) {
#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
- case OffloadArch::KIND: \
+ case llvm::NVPTX::GK_##KIND: \
return CudaVersion::MAX_VER;
#include "llvm/TargetParser/NVPTXTargetParser.def"
default:
@@ -127,33 +129,15 @@ bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
}
unsigned CudaArchToID(OffloadArch Arch) {
- switch (Arch) {
-#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
- case OffloadArch::KIND: \
- return SM_ID;
-#include "llvm/TargetParser/NVPTXTargetParser.def"
- default:
- break;
- }
- llvm_unreachable("invalid NVIDIA GPU architecture");
-}
-
-static llvm::NVPTX::GPUKind OffloadArchToNVPTXKind(OffloadArch Arch) {
- switch (Arch) {
-#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
- case OffloadArch::KIND: \
- return llvm::NVPTX::GK_##KIND;
-#include "llvm/TargetParser/NVPTXTargetParser.def"
- default:
- return llvm::NVPTX::GK_NONE;
- }
+ assert(Arch.isNVPTX() && "invalid NVIDIA GPU architecture");
+ return llvm::NVPTX::getSmVersion(Arch.nvptxKind());
}
bool IsNVIDIAAcceleratedOffloadArch(OffloadArch Arch) {
- return llvm::NVPTX::isAcceleratedArch(OffloadArchToNVPTXKind(Arch));
+ return Arch.isNVPTX() && llvm::NVPTX::isAcceleratedArch(Arch.nvptxKind());
}
bool IsNVIDIAFamilySpecificOffloadArch(OffloadArch Arch) {
- return llvm::NVPTX::isFamilySpecificArch(OffloadArchToNVPTXKind(Arch));
+ return Arch.isNVPTX() && llvm::NVPTX::isFamilySpecificArch(Arch.nvptxKind());
}
} // namespace clang
diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp
index 5d12f257f3680..55a0564cff89d 100644
--- a/clang/lib/Basic/OffloadArch.cpp
+++ b/clang/lib/Basic/OffloadArch.cpp
@@ -7,164 +7,101 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/OffloadArch.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/TargetParser/AMDGPUTargetParser.h"
+#include "llvm/TargetParser/NVPTXTargetParser.h"
#include "llvm/TargetParser/Triple.h"
namespace clang {
-namespace {
-struct OffloadArchToStringMap {
- OffloadArch Arch;
- const char *ArchName;
- const char *VirtualArchName;
-};
-} // namespace
+OffloadArch OffloadArch::CudaDefault() {
+ return getNVPTX(llvm::NVPTX::parseArch("sm_52"));
+}
-#define SM(sm) {OffloadArch::SM_##sm, "sm_" #sm, "compute_" #sm}
-#define GFX(gpu) {OffloadArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn"}
-static const OffloadArchToStringMap ArchNames[] = {
- // clang-format off
- {OffloadArch::Unused, "", ""},
- SM(20), {OffloadArch::SM_21, "sm_21", "compute_20"}, // Fermi
- SM(30), {OffloadArch::SM_32_, "sm_32", "compute_32"}, SM(35), SM(37), // Kepler
- SM(50), SM(52), SM(53), // Maxwell
- SM(60), SM(61), SM(62), // Pascal
- SM(70), SM(72), // Volta
- SM(75), // Turing
- SM(80), SM(86), // Ampere
- SM(87), // Jetson/Drive AGX Orin
- SM(88), // Ampere
- SM(89), // Ada Lovelace
- SM(90), // Hopper
- SM(90a), // Hopper
- SM(100), // Blackwell
- SM(100a), // Blackwell
- SM(100f), // Blackwell
- SM(101), // Blackwell
- SM(101a), // Blackwell
- SM(101f), // Blackwell
- SM(103), // Blackwell
- SM(103a), // Blackwell
- SM(103f), // Blackwell
- SM(110), // Blackwell
- SM(110a), // Blackwell
- SM(110f), // Blackwell
- SM(120), // Blackwell
- SM(120a), // Blackwell
- SM(120f), // Blackwell
- SM(121), // Blackwell
- SM(121a), // Blackwell
- SM(121f), // Blackwell
- GFX(600), // gfx600
- GFX(601), // gfx601
- GFX(602), // gfx602
- GFX(700), // gfx700
- GFX(701), // gfx701
- GFX(702), // gfx702
- GFX(703), // gfx703
- GFX(704), // gfx704
- GFX(705), // gfx705
- GFX(801), // gfx801
- GFX(802), // gfx802
- GFX(803), // gfx803
- GFX(805), // gfx805
- GFX(810), // gfx810
- {OffloadArch::GFX9_GENERIC, "gfx9-generic", "compute_amdgcn"},
- GFX(900), // gfx900
- GFX(902), // gfx902
- GFX(904), // gfx903
- GFX(906), // gfx906
- GFX(908), // gfx908
- GFX(909), // gfx909
- GFX(90a), // gfx90a
- GFX(90c), // gfx90c
- {OffloadArch::GFX9_4_GENERIC, "gfx9-4-generic", "compute_amdgcn"},
- GFX(942), // gfx942
- GFX(950), // gfx950
- {OffloadArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"},
- GFX(1010), // gfx1010
- GFX(1011), // gfx1011
- GFX(1012), // gfx1012
- GFX(1013), // gfx1013
- {OffloadArch::GFX10_3_GENERIC, "gfx10-3-generic", "compute_amdgcn"},
- GFX(1030), // gfx1030
- GFX(1031), // gfx1031
- GFX(1032), // gfx1032
- GFX(1033), // gfx1033
- GFX(1034), // gfx1034
- GFX(1035), // gfx1035
- GFX(1036), // gfx1036
- {OffloadArch::GFX11_GENERIC, "gfx11-generic", "compute_amdgcn"},
- GFX(1100), // gfx1100
- GFX(1101), // gfx1101
- GFX(1102), // gfx1102
- GFX(1103), // gfx1103
- GFX(1150), // gfx1150
- GFX(1151), // gfx1151
- GFX(1152), // gfx1152
- GFX(1153), // gfx1153
- GFX(1154), // gfx1154
- {OffloadArch::GFX11_7_GENERIC, "gfx11-7-generic", "compute_amdgcn"},
- GFX(1170), // gfx1170
- GFX(1171), // gfx1171
- GFX(1172), // gfx1172
- {OffloadArch::GFX12_GENERIC, "gfx12-generic", "compute_amdgcn"},
- GFX(1200), // gfx1200
- GFX(1201), // gfx1201
- {OffloadArch::GFX12_5_GENERIC, "gfx12-5-generic", "compute_amdgcn"},
- GFX(1250), // gfx1250
- GFX(1251), // gfx1251
- {OffloadArch::GFX13_GENERIC, "gfx13-generic", "compute_amdgcn"},
- GFX(1310), // gfx1310
- {OffloadArch::AMDGCNSPIRV, "amdgcnspirv", "compute_amdgcn"},
- // Intel CPUs
- {OffloadArch::GRANITERAPIDS, "graniterapids", ""},
- // Intel GPUS
- {OffloadArch::BMG_G21, "bmg_g21", ""},
- {OffloadArch::Generic, "generic", ""},
- // clang-format on
-};
-#undef SM
-#undef GFX
+OffloadArch OffloadArch::HIPDefault() {
+ return getAMDGPU(llvm::AMDGPU::parseArchAMDGCN("gfx906"));
+}
const char *OffloadArchToString(OffloadArch A) {
- auto Result =
- llvm::find_if(ArchNames, [A](const OffloadArchToStringMap &Map) {
- return A == Map.Arch;
- });
- if (Result == std::end(ArchNames))
+ switch (A.targetArch()) {
+ case OffloadArch::TargetArch::Unused:
+ return "";
+ case OffloadArch::TargetArch::Unknown:
return "unknown";
- return Result->ArchName;
+ case OffloadArch::TargetArch::NVPTX:
+ return llvm::NVPTX::getArchName(A.nvptxKind()).data();
+ case OffloadArch::TargetArch::AMDGPU:
+ return llvm::AMDGPU::getArchNameAMDGCN(A.amdgpuKind()).data();
+ case OffloadArch::TargetArch::SPIRV:
+ return "amdgcnspirv";
+ case OffloadArch::TargetArch::IntelCPU:
+ return "graniterapids";
+ case OffloadArch::TargetArch::IntelGPU:
+ return "bmg_g21";
+ case OffloadArch::TargetArch::Generic:
+ return "generic";
+ }
+ return "unknown";
}
const char *OffloadArchToVirtualArchString(OffloadArch A) {
- auto Result =
- llvm::find_if(ArchNames, [A](const OffloadArchToStringMap &Map) {
- return A == Map.Arch;
- });
- if (Result == std::end(ArchNames))
+ switch (A.targetArch()) {
+ case OffloadArch::TargetArch::NVPTX:
+ return llvm::NVPTX::getVirtualArch(A.nvptxKind()).data();
+ case OffloadArch::TargetArch::AMDGPU:
+ case OffloadArch::TargetArch::SPIRV:
+ return "compute_amdgcn";
+ case OffloadArch::TargetArch::Unknown:
return "unknown";
- return Result->VirtualArchName;
+ case OffloadArch::TargetArch::Unused:
+ case OffloadArch::TargetArch::IntelCPU:
+ case OffloadArch::TargetArch::IntelGPU:
+ case OffloadArch::TargetArch::Generic:
+ return "";
+ }
+ return "unknown";
}
OffloadArch StringToOffloadArch(llvm::StringRef S) {
- auto Result =
- llvm::find_if(ArchNames, [S](const OffloadArchToStringMap &Map) {
- return S == Map.ArchName;
- });
- if (Result == std::end(ArchNames))
- return OffloadArch::Unknown;
- return Result->Arch;
+ // The empty string denotes the "unused" architecture.
+ if (S.empty())
+ return OffloadArch::getUnused();
+
+ // Non-GPU-table pseudo/sentinel architectures.
+ if (S == "amdgcnspirv")
+ return OffloadArch::getSPIRV();
+ if (S == "generic")
+ return OffloadArch::getGeneric();
+ if (S == "graniterapids")
+ return OffloadArch::getIntel(OffloadArch::TargetArch::IntelCPU,
+ OffloadArch::IntelArch::GRANITERAPIDS);
+ if (S == "bmg_g21")
+ return OffloadArch::getIntel(OffloadArch::TargetArch::IntelGPU,
+ OffloadArch::IntelArch::BMG_G21);
+
+ // Otherwise defer to the vendor TargetParser GPU lists.
+ if (llvm::NVPTX::GPUKind NV = llvm::NVPTX::parseArch(S))
+ return OffloadArch::getNVPTX(NV);
+ if (llvm::AMDGPU::GPUKind AK = llvm::AMDGPU::parseArchAMDGCN(S))
+ return OffloadArch::getAMDGPU(AK);
+ return OffloadArch::getUnknown();
+}
+
+void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) {
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
+ Values.push_back(NAME);
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+ llvm::AMDGPU::fillValidArchListAMDGCN(Values, llvm::Triple::NoSubArch);
}
llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
OffloadArch ID) {
- if (ID == OffloadArch::AMDGCNSPIRV)
+ if (ID.isSPIRV())
return llvm::Triple(llvm::Triple::spirv64, llvm::Triple::NoSubArch,
llvm::Triple::AMD, llvm::Triple::AMDHSA);
- if (IsNVIDIAOffloadArch(ID)) {
+ if (ID.isNVPTX()) {
llvm::Triple::ArchType Arch = DefaultToolchainTriple.isArch64Bit()
? llvm::Triple::nvptx64
: llvm::Triple::nvptx;
@@ -172,7 +109,7 @@ llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
llvm::Triple::CUDA);
}
- if (IsAMDOffloadArch(ID))
+ if (ID.isAMDGPU())
return llvm::Triple("amdgcn-amd-amdhsa");
return {};
diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp
index 2e1d9abac8320..d2fed6a2f9787 100644
--- a/clang/lib/Basic/Targets/NVPTX.cpp
+++ b/clang/lib/Basic/Targets/NVPTX.cpp
@@ -64,7 +64,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
// Define available target features
// These must be defined in sorted order!
NoAsmVariants = true;
- GPU = OffloadArch::Unused;
+ GPU = OffloadArch::getUnused();
// PTX supports f16 as a fundamental type.
HasFastHalfType = true;
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index 72941fd65fda8..996b1a9730606 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -72,7 +72,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
- if (GPU != OffloadArch::Unused)
+ if (!GPU.isUnused())
Features[OffloadArchToString(GPU)] = true;
// Only add PTX feature if explicitly requested. Otherwise, let the backend
// use the minimum required PTX version for the target SM.
@@ -131,18 +131,16 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
}
bool isValidCPUName(StringRef Name) const override {
- return StringToOffloadArch(Name) != OffloadArch::Unknown;
+ return !StringToOffloadArch(Name).isUnknown();
}
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
- for (int i = static_cast<int>(OffloadArch::SM_20);
- i < static_cast<int>(OffloadArch::Generic); ++i)
- Values.emplace_back(OffloadArchToString(static_cast<OffloadArch>(i)));
+ fillValidOffloadArchList(Values);
}
bool setCPU(StringRef Name) override {
GPU = StringToOffloadArch(Name);
- return GPU != OffloadArch::Unknown;
+ return !GPU.isUnknown();
}
void setSupportedOpenCLOpts() override {
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 38795f7c2ae7a..5bd46db170d96 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -961,7 +961,7 @@ static TripleSet inferOffloadToolchains(Compilation &C,
TripleSet Triples;
for (llvm::StringRef Arch : Archs) {
OffloadArch ID = StringToOffloadArch(Arch);
- if (ID == OffloadArch::Unknown)
+ if (ID.isUnknown())
ID = StringToOffloadArch(
getProcessorFromTargetID(llvm::Triple("amdgcn-amd-amdhsa"), Arch));
@@ -975,13 +975,12 @@ static TripleSet inferOffloadToolchains(Compilation &C,
<< "CUDA" << Arch;
return {};
}
- if (Kind == Action::OFK_OpenMP &&
- (ID == OffloadArch::Unknown || ID == OffloadArch::Unused)) {
+ if (Kind == Action::OFK_OpenMP && (ID.isUnknown() || ID.isUnused())) {
C.getDriver().Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch)
<< Arch;
return {};
}
- if (ID == OffloadArch::Unknown || ID == OffloadArch::Unused) {
+ if (ID.isUnknown() || ID.isUnused()) {
C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
<< "offload" << Arch;
return {};
@@ -3466,7 +3465,7 @@ class OffloadingActionBuilder final {
bool Relocatable = false;
/// Default GPU architecture if there's no one specified.
- OffloadArch DefaultOffloadArch = OffloadArch::Unknown;
+ OffloadArch DefaultOffloadArch = OffloadArch::getUnknown();
/// Compilation unit ID specified by option '-fuse-cuid=' or'-cuid='.
const CUIDOptions &CUIDOpts;
@@ -3644,7 +3643,7 @@ class OffloadingActionBuilder final {
CudaActionBuilder(Compilation &C, DerivedArgList &Args,
const InputList &Inputs)
: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {
- DefaultOffloadArch = OffloadArch::CudaDefault;
+ DefaultOffloadArch = OffloadArch::CudaDefault();
}
ActionBuilderReturnCode
@@ -3769,7 +3768,7 @@ class OffloadingActionBuilder final {
const InputList &Inputs)
: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
- DefaultOffloadArch = OffloadArch::HIPDefault;
+ DefaultOffloadArch = OffloadArch::HIPDefault();
if (Args.hasArg(options::OPT_fhip_emit_relocatable,
options::OPT_fno_hip_emit_relocatable)) {
@@ -4882,13 +4881,12 @@ static StringRef getCanonicalArchString(Compilation &C,
// expecting the triple to be only NVPTX / AMDGPU.
OffloadArch Arch =
StringToOffloadArch(getProcessorFromTargetID(Triple, ArchStr));
- if (Triple.isNVPTX() &&
- (Arch == OffloadArch::Unknown || !IsNVIDIAOffloadArch(Arch))) {
+ if (Triple.isNVPTX() && (Arch.isUnknown() || !IsNVIDIAOffloadArch(Arch))) {
C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
<< "CUDA" << ArchStr;
return StringRef();
} else if (Triple.isAMDGPU() &&
- (Arch == OffloadArch::Unknown || !IsAMDOffloadArch(Arch))) {
+ (Arch.isUnknown() || !IsAMDOffloadArch(Arch))) {
C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
<< "HIP" << ArchStr;
return StringRef();
@@ -4992,12 +4990,12 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
if (Archs.empty()) {
if (Kind == Action::OFK_Cuda) {
Archs.insert(OffloadArchToString(TC.getTriple().isSPIRV()
- ? OffloadArch::Unused
- : OffloadArch::CudaDefault));
+ ? OffloadArch::getUnused()
+ : OffloadArch::CudaDefault()));
} else if (Kind == Action::OFK_HIP) {
Archs.insert(OffloadArchToString(TC.getTriple().isSPIRV()
- ? OffloadArch::Generic
- : OffloadArch::HIPDefault));
+ ? OffloadArch::getGeneric()
+ : OffloadArch::HIPDefault()));
} else if (Kind == Action::OFK_SYCL) {
Archs.insert(StringRef());
} else if (Kind == Action::OFK_OpenMP) {
diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp
index 8e4d44071ef55..b397ee4c5b075 100644
--- a/clang/lib/Driver/OffloadBundler.cpp
+++ b/clang/lib/Driver/OffloadBundler.cpp
@@ -83,8 +83,7 @@ OffloadTargetInfo::OffloadTargetInfo(const StringRef Target,
StringRef TargetIdWithFeature =
Components.size() == 6 ? Components.back() : "";
StringRef TargetId = TargetIdWithFeature.split(':').first;
- if (!TargetId.empty() &&
- clang::StringToOffloadArch(TargetId) != clang::OffloadArch::Unknown)
+ if (!TargetId.empty() && !clang::StringToOffloadArch(TargetId).isUnknown())
this->TargetID = TargetIdWithFeature;
else
this->TargetID = "";
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index b7e257b2c0207..93e335ca8bb82 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -235,14 +235,12 @@ CudaInstallationDetector::CudaInstallationDetector(
// CUDA-9+ uses single libdevice file for all GPU variants.
std::string FilePath = LibDevicePath + "/libdevice.10.bc";
if (FS.exists(FilePath)) {
- for (int Arch = (int)OffloadArch::SM_30, E = (int)OffloadArch::LAST;
- Arch < E; ++Arch) {
- OffloadArch OA = static_cast<OffloadArch>(Arch);
- if (!IsNVIDIAOffloadArch(OA))
- continue;
- std::string OffloadArchName(OffloadArchToString(OA));
- LibDeviceMap[OffloadArchName] = FilePath;
- }
+ // CUDA-9+ uses a single libdevice file for every NVIDIA GPU variant
+ // (sm_30 and newer).
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
+ if ((SM_ID) >= 300) \
+ LibDeviceMap[NAME] = FilePath;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
}
} else {
std::error_code EC;
@@ -326,14 +324,15 @@ void CudaInstallationDetector::AddCudaIncludeArgs(
void CudaInstallationDetector::CheckCudaVersionSupportsArch(
OffloadArch Arch) const {
- if (Arch == OffloadArch::Unknown || Version == CudaVersion::UNKNOWN ||
- ArchsWithBadVersion[(int)Arch])
+ // Only NVIDIA architectures depend on the CUDA toolkit version.
+ if (!Arch.isNVPTX() || Version == CudaVersion::UNKNOWN ||
+ ArchsWithBadVersion[Arch.nvptxKind()])
return;
auto MinVersion = MinVersionForOffloadArch(Arch);
auto MaxVersion = MaxVersionForOffloadArch(Arch);
if (Version < MinVersion || Version > MaxVersion) {
- ArchsWithBadVersion[(int)Arch] = true;
+ ArchsWithBadVersion[Arch.nvptxKind()] = true;
D.Diag(diag::err_drv_cuda_version_unsupported)
<< OffloadArchToString(Arch) << CudaVersionToString(MinVersion)
<< CudaVersionToString(MaxVersion) << InstallPath
@@ -414,7 +413,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
// Obtain architecture from the action.
- assert(GPUArch.Arch != OffloadArch::Unknown &&
+ assert(!GPUArch.Arch.isUnknown() &&
"Device action expected to have an architecture.");
// Check that our installation's ptxas supports gpu_arch.
@@ -778,7 +777,7 @@ NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
if (!DAL->hasArg(options::OPT_march_EQ) && OffloadKind != Action::OFK_None) {
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
- OffloadArchToString(OffloadArch::CudaDefault));
+ OffloadArchToString(OffloadArch::CudaDefault()));
} else if (DAL->getLastArgValue(options::OPT_march_EQ) == "generic" &&
OffloadKind == Action::OFK_None) {
DAL->eraseArg(options::OPT_march_EQ);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 492b125587344..690821a8e9ef9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -72,6 +72,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/NVPTXTargetParser.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>
@@ -6129,8 +6130,8 @@ Sema::CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads,
// launch bounds attribute within ompx_attribute to support other archs.
if (!IgnoreArch) {
// '.maxclusterrank' ptx directive requires .target sm_90 or higher.
- auto SM = getOffloadArch(Context.getTargetInfo());
- if (SM == OffloadArch::Unknown || SM < OffloadArch::SM_90) {
+ OffloadArch SM = getOffloadArch(Context.getTargetInfo());
+ if (SM.isUnknown() || llvm::NVPTX::getSmVersion(SM.nvptxKind()) < 900) {
Diag(MaxBlocks->getBeginLoc(), diag::warn_cuda_maxclusterrank_sm_90)
<< OffloadArchToString(SM) << CI << MaxBlocks->getSourceRange();
// Ignore it by setting MaxBlocks to null;
@@ -6244,7 +6245,8 @@ void Sema::addNoClusterAttr(Decl *D, const AttributeCommonInfo &CI) {
static void handleClusterDimsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const TargetInfo &TTI = S.Context.getTargetInfo();
OffloadArch Arch = StringToOffloadArch(TTI.getTargetOpts().CPU);
- if ((TTI.getTriple().isNVPTX() && Arch < clang::OffloadArch::SM_90) ||
+ if ((TTI.getTriple().isNVPTX() &&
+ llvm::NVPTX::getSmVersion(Arch.nvptxKind()) < 900) ||
(TTI.getTriple().isAMDGPU() &&
!TTI.hasFeatureEnabled(TTI.getTargetOpts().FeatureMap, "clusters"))) {
S.Diag(AL.getLoc(), diag::err_cluster_attr_not_supported) << AL;
@@ -6263,7 +6265,8 @@ static void handleClusterDimsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleNoClusterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const TargetInfo &TTI = S.Context.getTargetInfo();
OffloadArch Arch = StringToOffloadArch(TTI.getTargetOpts().CPU);
- if ((TTI.getTriple().isNVPTX() && Arch < clang::OffloadArch::SM_90) ||
+ if ((TTI.getTriple().isNVPTX() &&
+ llvm::NVPTX::getSmVersion(Arch.nvptxKind()) < 900) ||
(TTI.getTriple().isAMDGPU() &&
!TTI.hasFeatureEnabled(TTI.getTargetOpts().FeatureMap, "clusters"))) {
S.Diag(AL.getLoc(), diag::err_cluster_attr_not_supported) << AL;
diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c
index decbdfd44d6eb..922a2eb1d8c3a 100644
--- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c
+++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c
@@ -59,7 +59,6 @@
// CHECK-SAME: {{^}}, gfx803
// CHECK-SAME: {{^}}, gfx805
// CHECK-SAME: {{^}}, gfx810
-// CHECK-SAME: {{^}}, gfx9-generic
// CHECK-SAME: {{^}}, gfx900
// CHECK-SAME: {{^}}, gfx902
// CHECK-SAME: {{^}}, gfx904
@@ -68,15 +67,12 @@
// CHECK-SAME: {{^}}, gfx909
// CHECK-SAME: {{^}}, gfx90a
// CHECK-SAME: {{^}}, gfx90c
-// CHECK-SAME: {{^}}, gfx9-4-generic
// CHECK-SAME: {{^}}, gfx942
// CHECK-SAME: {{^}}, gfx950
-// CHECK-SAME: {{^}}, gfx10-1-generic
// CHECK-SAME: {{^}}, gfx1010
// CHECK-SAME: {{^}}, gfx1011
// CHECK-SAME: {{^}}, gfx1012
// CHECK-SAME: {{^}}, gfx1013
-// CHECK-SAME: {{^}}, gfx10-3-generic
// CHECK-SAME: {{^}}, gfx1030
// CHECK-SAME: {{^}}, gfx1031
// CHECK-SAME: {{^}}, gfx1032
@@ -84,7 +80,6 @@
// CHECK-SAME: {{^}}, gfx1034
// CHECK-SAME: {{^}}, gfx1035
// CHECK-SAME: {{^}}, gfx1036
-// CHECK-SAME: {{^}}, gfx11-generic
// CHECK-SAME: {{^}}, gfx1100
// CHECK-SAME: {{^}}, gfx1101
// CHECK-SAME: {{^}}, gfx1102
@@ -94,17 +89,39 @@
// CHECK-SAME: {{^}}, gfx1152
// CHECK-SAME: {{^}}, gfx1153
// CHECK-SAME: {{^}}, gfx1154
-// CHECK-SAME: {{^}}, gfx11-7-generic
// CHECK-SAME: {{^}}, gfx1170
// CHECK-SAME: {{^}}, gfx1171
// CHECK-SAME: {{^}}, gfx1172
-// CHECK-SAME: {{^}}, gfx12-generic
// CHECK-SAME: {{^}}, gfx1200
// CHECK-SAME: {{^}}, gfx1201
-// CHECK-SAME: {{^}}, gfx12-5-generic
// CHECK-SAME: {{^}}, gfx1250
// CHECK-SAME: {{^}}, gfx1251
-// CHECK-SAME: {{^}}, gfx13-generic
// CHECK-SAME: {{^}}, gfx1310
-// CHECK-SAME: {{^}}, amdgcnspirv
+// CHECK-SAME: {{^}}, gfx9-generic
+// CHECK-SAME: {{^}}, gfx9-4-generic
+// CHECK-SAME: {{^}}, gfx10-1-generic
+// CHECK-SAME: {{^}}, gfx10-3-generic
+// CHECK-SAME: {{^}}, gfx11-generic
+// CHECK-SAME: {{^}}, gfx11-7-generic
+// CHECK-SAME: {{^}}, gfx12-generic
+// CHECK-SAME: {{^}}, gfx12-5-generic
+// CHECK-SAME: {{^}}, gfx13-generic
+// CHECK-SAME: {{^}}, tahiti
+// CHECK-SAME: {{^}}, pitcairn
+// CHECK-SAME: {{^}}, verde
+// CHECK-SAME: {{^}}, hainan
+// CHECK-SAME: {{^}}, oland
+// CHECK-SAME: {{^}}, kaveri
+// CHECK-SAME: {{^}}, hawaii
+// CHECK-SAME: {{^}}, kabini
+// CHECK-SAME: {{^}}, mullins
+// CHECK-SAME: {{^}}, bonaire
+// CHECK-SAME: {{^}}, carrizo
+// CHECK-SAME: {{^}}, iceland
+// CHECK-SAME: {{^}}, tonga
+// CHECK-SAME: {{^}}, fiji
+// CHECK-SAME: {{^}}, polaris10
+// CHECK-SAME: {{^}}, polaris11
+// CHECK-SAME: {{^}}, tongapro
+// CHECK-SAME: {{^}}, stoney
// CHECK-SAME: {{$}}
diff --git a/clang/unittests/Basic/OffloadArchTest.cpp b/clang/unittests/Basic/OffloadArchTest.cpp
index c19ad0043d774..36dd958f0d896 100644
--- a/clang/unittests/Basic/OffloadArchTest.cpp
+++ b/clang/unittests/Basic/OffloadArchTest.cpp
@@ -11,26 +11,49 @@
using namespace clang;
-TEST(OffloadArchTest, basic) {
- EXPECT_TRUE(IsNVIDIAOffloadArch(OffloadArch::SM_20));
- EXPECT_TRUE(IsNVIDIAOffloadArch(OffloadArch::SM_120a));
- EXPECT_FALSE(IsNVIDIAOffloadArch(OffloadArch::GFX600));
-
- EXPECT_FALSE(IsAMDOffloadArch(OffloadArch::SM_120a));
- EXPECT_TRUE(IsAMDOffloadArch(OffloadArch::GFX600));
- EXPECT_TRUE(IsAMDOffloadArch(OffloadArch::GFX1201));
- EXPECT_TRUE(IsAMDOffloadArch(OffloadArch::GFX12_GENERIC));
- EXPECT_TRUE(IsAMDOffloadArch(OffloadArch::AMDGCNSPIRV));
- EXPECT_FALSE(IsAMDOffloadArch(OffloadArch::GRANITERAPIDS));
-
- EXPECT_TRUE(IsIntelOffloadArch(OffloadArch::GRANITERAPIDS));
- EXPECT_TRUE(IsIntelCPUOffloadArch(OffloadArch::GRANITERAPIDS));
- EXPECT_FALSE(IsIntelGPUOffloadArch(OffloadArch::GRANITERAPIDS));
- EXPECT_TRUE(IsIntelOffloadArch(OffloadArch::BMG_G21));
- EXPECT_FALSE(IsIntelCPUOffloadArch(OffloadArch::BMG_G21));
- EXPECT_TRUE(IsIntelGPUOffloadArch(OffloadArch::BMG_G21));
-
- EXPECT_FALSE(IsNVIDIAOffloadArch(OffloadArch::Generic));
- EXPECT_FALSE(IsAMDOffloadArch(OffloadArch::Generic));
- EXPECT_FALSE(IsIntelOffloadArch(OffloadArch::Generic));
+static OffloadArch parse(llvm::StringRef S) { return StringToOffloadArch(S); }
+
+TEST(OffloadArchTest, VendorClassification) {
+ EXPECT_TRUE(IsNVIDIAOffloadArch(parse("sm_20")));
+ EXPECT_TRUE(IsNVIDIAOffloadArch(parse("sm_120a")));
+ EXPECT_FALSE(IsNVIDIAOffloadArch(parse("gfx600")));
+
+ EXPECT_FALSE(IsAMDOffloadArch(parse("sm_120a")));
+ EXPECT_TRUE(IsAMDOffloadArch(parse("gfx600")));
+ EXPECT_TRUE(IsAMDOffloadArch(parse("gfx1201")));
+ EXPECT_TRUE(IsAMDOffloadArch(parse("gfx12-generic")));
+ EXPECT_TRUE(IsAMDOffloadArch(parse("amdgcnspirv")));
+ EXPECT_FALSE(IsAMDOffloadArch(parse("graniterapids")));
+
+ EXPECT_TRUE(IsIntelOffloadArch(parse("graniterapids")));
+ EXPECT_TRUE(IsIntelCPUOffloadArch(parse("graniterapids")));
+ EXPECT_FALSE(IsIntelGPUOffloadArch(parse("graniterapids")));
+ EXPECT_TRUE(IsIntelOffloadArch(parse("bmg_g21")));
+ EXPECT_FALSE(IsIntelCPUOffloadArch(parse("bmg_g21")));
+ EXPECT_TRUE(IsIntelGPUOffloadArch(parse("bmg_g21")));
+
+ EXPECT_FALSE(IsNVIDIAOffloadArch(parse("generic")));
+ EXPECT_FALSE(IsAMDOffloadArch(parse("generic")));
+ EXPECT_FALSE(IsIntelOffloadArch(parse("generic")));
+}
+
+TEST(OffloadArchTest, Unknown) {
+ EXPECT_TRUE(parse("not-a-real-arch").isUnknown());
+ EXPECT_TRUE(parse("").isUnused());
+}
+
+// Names must round-trip through parse -> string.
+TEST(OffloadArchTest, RoundTrip) {
+ for (const char *Name :
+ {"sm_52", "sm_90a", "gfx906", "gfx1201", "gfx12-generic", "amdgcnspirv",
+ "graniterapids", "bmg_g21", "generic"}) {
+ OffloadArch A = parse(Name);
+ EXPECT_FALSE(A.isUnknown()) << Name;
+ EXPECT_STREQ(OffloadArchToString(A), Name);
+ }
+}
+
+TEST(OffloadArchTest, Defaults) {
+ EXPECT_STREQ(OffloadArchToString(OffloadArch::CudaDefault()), "sm_52");
+ EXPECT_STREQ(OffloadArchToString(OffloadArch::HIPDefault()), "gfx906");
}
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index fd0072c89be23..c2e394d82292f 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -31,7 +31,7 @@ class Triple;
namespace AMDGPU {
/// GPU kinds supported by the AMDGPU target.
-enum GPUKind : uint32_t {
+enum GPUKind : uint8_t {
// Not specified processor.
GK_NONE = 0,
diff --git a/llvm/include/llvm/TargetParser/NVPTXTargetParser.h b/llvm/include/llvm/TargetParser/NVPTXTargetParser.h
index a49130b99ba76..446f5c47aeaf3 100644
--- a/llvm/include/llvm/TargetParser/NVPTXTargetParser.h
+++ b/llvm/include/llvm/TargetParser/NVPTXTargetParser.h
@@ -17,11 +17,15 @@ namespace llvm {
namespace NVPTX {
/// GPU kinds supported by the NVPTX target.
-enum GPUKind : uint32_t {
+enum GPUKind : uint8_t {
GK_NONE = 0,
#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
GK_##KIND,
#include "llvm/TargetParser/NVPTXTargetParser.def"
+
+ // Alias for the last GPUKind. Keep in sync with the final .def row.
+ // FIXME: Should be generated once the GPU list moves to TableGen.
+ GK_LAST = GK_SM_121f,
};
/// Suffix class of an NVPTX architecture name. Enumerator spellings match the
More information about the cfe-commits
mailing list