[clang] [llvm] NVPTX: Add target names in TargetParser (PR #212734)

Matt Arsenault via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 29 04:15:21 PDT 2026


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

>From 22d90e4c3813dae86e2d33e8f2fbad72921e60c7 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 29 Jul 2026 10:26:07 +0200
Subject: [PATCH] NVPTX: Add target names in TargetParser

Track the canonical sm name and other target information.
This will eventually be used to reduce the pain of maintaining
OffloadArch in clang; all of the dijoint targets share an
enum which makes target specific covered switches annoying.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
 clang/lib/Basic/Cuda.cpp                      | 180 +++---------------
 .../llvm/TargetParser/NVPTXTargetParser.def   |  71 +++++++
 .../llvm/TargetParser/NVPTXTargetParser.h     |  69 +++++++
 llvm/lib/TargetParser/CMakeLists.txt          |   1 +
 llvm/lib/TargetParser/NVPTXTargetParser.cpp   |  73 +++++++
 llvm/unittests/TargetParser/CMakeLists.txt    |   1 +
 .../TargetParser/NVPTXTargetParserTest.cpp    |  72 +++++++
 .../secondary/llvm/lib/TargetParser/BUILD.gn  |   1 +
 .../llvm/unittests/TargetParser/BUILD.gn      |   1 +
 9 files changed, 313 insertions(+), 156 deletions(-)
 create mode 100644 llvm/include/llvm/TargetParser/NVPTXTargetParser.def
 create mode 100644 llvm/include/llvm/TargetParser/NVPTXTargetParser.h
 create mode 100644 llvm/lib/TargetParser/NVPTXTargetParser.cpp
 create mode 100644 llvm/unittests/TargetParser/NVPTXTargetParserTest.cpp

diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp
index 326c1ceddd154..b61d890e23dfe 100644
--- a/clang/lib/Basic/Cuda.cpp
+++ b/clang/lib/Basic/Cuda.cpp
@@ -3,6 +3,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/VersionTuple.h"
+#include "llvm/TargetParser/NVPTXTargetParser.h"
 
 namespace clang {
 
@@ -85,59 +86,10 @@ CudaVersion MinVersionForOffloadArch(OffloadArch A) {
     return CudaVersion::CUDA_70;
 
   switch (A) {
-  case OffloadArch::SM_20:
-  case OffloadArch::SM_21:
-  case OffloadArch::SM_30:
-  case OffloadArch::SM_32_:
-  case OffloadArch::SM_35:
-  case OffloadArch::SM_37:
-  case OffloadArch::SM_50:
-  case OffloadArch::SM_52:
-  case OffloadArch::SM_53:
-    return CudaVersion::CUDA_70;
-  case OffloadArch::SM_60:
-  case OffloadArch::SM_61:
-  case OffloadArch::SM_62:
-    return CudaVersion::CUDA_80;
-  case OffloadArch::SM_70:
-    return CudaVersion::CUDA_90;
-  case OffloadArch::SM_72:
-    return CudaVersion::CUDA_91;
-  case OffloadArch::SM_75:
-    return CudaVersion::CUDA_100;
-  case OffloadArch::SM_80:
-    return CudaVersion::CUDA_110;
-  case OffloadArch::SM_86:
-    return CudaVersion::CUDA_111;
-  case OffloadArch::SM_87:
-    return CudaVersion::CUDA_114;
-  case OffloadArch::SM_89:
-  case OffloadArch::SM_90:
-    return CudaVersion::CUDA_118;
-  case OffloadArch::SM_90a:
-    return CudaVersion::CUDA_120;
-  case OffloadArch::SM_100:
-  case OffloadArch::SM_100a:
-  case OffloadArch::SM_101:
-  case OffloadArch::SM_101a:
-  case OffloadArch::SM_120:
-  case OffloadArch::SM_120a:
-    return CudaVersion::CUDA_128;
-  case OffloadArch::SM_100f:
-  case OffloadArch::SM_101f:
-  case OffloadArch::SM_103:
-  case OffloadArch::SM_103a:
-  case OffloadArch::SM_103f:
-  case OffloadArch::SM_120f:
-  case OffloadArch::SM_121:
-  case OffloadArch::SM_121a:
-  case OffloadArch::SM_121f:
-    return CudaVersion::CUDA_129;
-  case OffloadArch::SM_88:
-  case OffloadArch::SM_110:
-  case OffloadArch::SM_110a:
-  case OffloadArch::SM_110f:
-    return CudaVersion::CUDA_130;
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case OffloadArch::KIND:                                                      \
+    return CudaVersion::MIN_VER;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
   default:
     llvm_unreachable("invalid enum");
   }
@@ -151,19 +103,10 @@ CudaVersion MaxVersionForOffloadArch(OffloadArch A) {
   switch (A) {
   case OffloadArch::Unknown:
     return CudaVersion::UNKNOWN;
-  case OffloadArch::SM_20:
-  case OffloadArch::SM_21:
-    return CudaVersion::CUDA_80;
-  case OffloadArch::SM_30:
-  case OffloadArch::SM_32_:
-    return CudaVersion::CUDA_102;
-  case OffloadArch::SM_35:
-  case OffloadArch::SM_37:
-    return CudaVersion::CUDA_118;
-  case OffloadArch::SM_101:
-  case OffloadArch::SM_101a:
-  case OffloadArch::SM_101f:
-    return CudaVersion::CUDA_129;
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case OffloadArch::KIND:                                                      \
+    return CudaVersion::MAX_VER;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
   default:
     return CudaVersion::NEW;
   }
@@ -185,107 +128,32 @@ bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
 
 unsigned CudaArchToID(OffloadArch Arch) {
   switch (Arch) {
-  case OffloadArch::SM_20:
-    return 200;
-  case OffloadArch::SM_21:
-    return 210;
-  case OffloadArch::SM_30:
-    return 300;
-  case OffloadArch::SM_32_:
-    return 320;
-  case OffloadArch::SM_35:
-    return 350;
-  case OffloadArch::SM_37:
-    return 370;
-  case OffloadArch::SM_50:
-    return 500;
-  case OffloadArch::SM_52:
-    return 520;
-  case OffloadArch::SM_53:
-    return 530;
-  case OffloadArch::SM_60:
-    return 600;
-  case OffloadArch::SM_61:
-    return 610;
-  case OffloadArch::SM_62:
-    return 620;
-  case OffloadArch::SM_70:
-    return 700;
-  case OffloadArch::SM_72:
-    return 720;
-  case OffloadArch::SM_75:
-    return 750;
-  case OffloadArch::SM_80:
-    return 800;
-  case OffloadArch::SM_86:
-    return 860;
-  case OffloadArch::SM_87:
-    return 870;
-  case OffloadArch::SM_88:
-    return 880;
-  case OffloadArch::SM_89:
-    return 890;
-  case OffloadArch::SM_90:
-  case OffloadArch::SM_90a:
-    return 900;
-  case OffloadArch::SM_100:
-  case OffloadArch::SM_100a:
-  case OffloadArch::SM_100f:
-    return 1000;
-  case OffloadArch::SM_101:
-  case OffloadArch::SM_101a:
-  case OffloadArch::SM_101f:
-    return 1010;
-  case OffloadArch::SM_103:
-  case OffloadArch::SM_103a:
-  case OffloadArch::SM_103f:
-    return 1030;
-  case OffloadArch::SM_110:
-  case OffloadArch::SM_110a:
-  case OffloadArch::SM_110f:
-    return 1100;
-  case OffloadArch::SM_120:
-  case OffloadArch::SM_120a:
-  case OffloadArch::SM_120f:
-    return 1200;
-  case OffloadArch::SM_121:
-  case OffloadArch::SM_121a:
-  case OffloadArch::SM_121f:
-    return 1210;
+#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");
 }
 
-bool IsNVIDIAAcceleratedOffloadArch(OffloadArch Arch) {
+static llvm::NVPTX::GPUKind OffloadArchToNVPTXKind(OffloadArch Arch) {
   switch (Arch) {
-  case OffloadArch::SM_90a:
-  case OffloadArch::SM_100a:
-  case OffloadArch::SM_101a:
-  case OffloadArch::SM_103a:
-  case OffloadArch::SM_110a:
-  case OffloadArch::SM_120a:
-  case OffloadArch::SM_121a:
-    return true;
+#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 false;
+    return llvm::NVPTX::GK_NONE;
   }
 }
 
+bool IsNVIDIAAcceleratedOffloadArch(OffloadArch Arch) {
+  return llvm::NVPTX::isAcceleratedArch(OffloadArchToNVPTXKind(Arch));
+}
+
 bool IsNVIDIAFamilySpecificOffloadArch(OffloadArch Arch) {
-  if (IsNVIDIAAcceleratedOffloadArch(Arch))
-    return true;
-  switch (Arch) {
-  case OffloadArch::SM_100f:
-  case OffloadArch::SM_101f:
-  case OffloadArch::SM_103f:
-  case OffloadArch::SM_110f:
-  case OffloadArch::SM_120f:
-  case OffloadArch::SM_121f:
-    return true;
-  default:
-    return false;
-  }
+  return llvm::NVPTX::isFamilySpecificArch(OffloadArchToNVPTXKind(Arch));
 }
 } // namespace clang
diff --git a/llvm/include/llvm/TargetParser/NVPTXTargetParser.def b/llvm/include/llvm/TargetParser/NVPTXTargetParser.def
new file mode 100644
index 0000000000000..3f980ba0a8b59
--- /dev/null
+++ b/llvm/include/llvm/TargetParser/NVPTXTargetParser.def
@@ -0,0 +1,71 @@
+//===--- NVPTXTargetParser.def - NVPTX target data -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is the single source of truth for the NVPTX (CUDA) GPU list. Each
+// row describes one virtual architecture (sm_XX). Adding a new target is a
+// single row here.
+//
+//   NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)
+//     NAME     - Canonical processor name string, e.g. "sm_90".
+//     KIND     - GPUKind enumerator suffix; the enumerator is GK_<KIND>
+//     VIRTUAL  - Virtual (compute_) arch name string, e.g. "compute_90".
+//     SM_ID    - Numeric compute-capability id (sm_90 -> 900).
+//     MIN_VER  - Earliest supporting CudaVersion
+//     MAX_VER  - Latest supporting CudaVersion.
+//     SUFFIX   - Arch suffix class: NONE, ACCELERATED (sm_90a), FAMILY (sm_90f).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef NVPTX_GPU
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)
+#endif
+
+NVPTX_GPU("sm_20",   SM_20,   "compute_20",   200,  CUDA_70,  CUDA_80,  NONE)
+NVPTX_GPU("sm_21",   SM_21,   "compute_20",   210,  CUDA_70,  CUDA_80,  NONE)
+NVPTX_GPU("sm_30",   SM_30,   "compute_30",   300,  CUDA_70,  CUDA_102, NONE)
+
+// SM_32_ carries a trailing underscore to dodge a sys/mac.h macro clash on AIX
+NVPTX_GPU("sm_32",   SM_32_,  "compute_32",   320,  CUDA_70,  CUDA_102, NONE)
+NVPTX_GPU("sm_35",   SM_35,   "compute_35",   350,  CUDA_70,  CUDA_118, NONE)
+NVPTX_GPU("sm_37",   SM_37,   "compute_37",   370,  CUDA_70,  CUDA_118, NONE)
+NVPTX_GPU("sm_50",   SM_50,   "compute_50",   500,  CUDA_70,  NEW,      NONE)
+NVPTX_GPU("sm_52",   SM_52,   "compute_52",   520,  CUDA_70,  NEW,      NONE)
+NVPTX_GPU("sm_53",   SM_53,   "compute_53",   530,  CUDA_70,  NEW,      NONE)
+NVPTX_GPU("sm_60",   SM_60,   "compute_60",   600,  CUDA_80,  NEW,      NONE)
+NVPTX_GPU("sm_61",   SM_61,   "compute_61",   610,  CUDA_80,  NEW,      NONE)
+NVPTX_GPU("sm_62",   SM_62,   "compute_62",   620,  CUDA_80,  NEW,      NONE)
+NVPTX_GPU("sm_70",   SM_70,   "compute_70",   700,  CUDA_90,  NEW,      NONE)
+NVPTX_GPU("sm_72",   SM_72,   "compute_72",   720,  CUDA_91,  NEW,      NONE)
+NVPTX_GPU("sm_75",   SM_75,   "compute_75",   750,  CUDA_100, NEW,      NONE)
+NVPTX_GPU("sm_80",   SM_80,   "compute_80",   800,  CUDA_110, NEW,      NONE)
+NVPTX_GPU("sm_86",   SM_86,   "compute_86",   860,  CUDA_111, NEW,      NONE)
+NVPTX_GPU("sm_87",   SM_87,   "compute_87",   870,  CUDA_114, NEW,      NONE)
+NVPTX_GPU("sm_88",   SM_88,   "compute_88",   880,  CUDA_130, NEW,      NONE)
+NVPTX_GPU("sm_89",   SM_89,   "compute_89",   890,  CUDA_118, NEW,      NONE)
+NVPTX_GPU("sm_90",   SM_90,   "compute_90",   900,  CUDA_118, NEW,      NONE)
+NVPTX_GPU("sm_90a",  SM_90a,  "compute_90a",  900,  CUDA_120, NEW,      ACCELERATED)
+NVPTX_GPU("sm_100",  SM_100,  "compute_100",  1000, CUDA_128, NEW,      NONE)
+NVPTX_GPU("sm_100a", SM_100a, "compute_100a", 1000, CUDA_128, NEW,      ACCELERATED)
+NVPTX_GPU("sm_100f", SM_100f, "compute_100f", 1000, CUDA_129, NEW,      FAMILY)
+NVPTX_GPU("sm_101",  SM_101,  "compute_101",  1010, CUDA_128, CUDA_129, NONE)
+NVPTX_GPU("sm_101a", SM_101a, "compute_101a", 1010, CUDA_128, CUDA_129, ACCELERATED)
+NVPTX_GPU("sm_101f", SM_101f, "compute_101f", 1010, CUDA_129, CUDA_129, FAMILY)
+NVPTX_GPU("sm_103",  SM_103,  "compute_103",  1030, CUDA_129, NEW,      NONE)
+NVPTX_GPU("sm_103a", SM_103a, "compute_103a", 1030, CUDA_129, NEW,      ACCELERATED)
+NVPTX_GPU("sm_103f", SM_103f, "compute_103f", 1030, CUDA_129, NEW,      FAMILY)
+NVPTX_GPU("sm_110",  SM_110,  "compute_110",  1100, CUDA_130, NEW,      NONE)
+NVPTX_GPU("sm_110a", SM_110a, "compute_110a", 1100, CUDA_130, NEW,      ACCELERATED)
+NVPTX_GPU("sm_110f", SM_110f, "compute_110f", 1100, CUDA_130, NEW,      FAMILY)
+NVPTX_GPU("sm_120",  SM_120,  "compute_120",  1200, CUDA_128, NEW,      NONE)
+NVPTX_GPU("sm_120a", SM_120a, "compute_120a", 1200, CUDA_128, NEW,      ACCELERATED)
+NVPTX_GPU("sm_120f", SM_120f, "compute_120f", 1200, CUDA_129, NEW,      FAMILY)
+NVPTX_GPU("sm_121",  SM_121,  "compute_121",  1210, CUDA_129, NEW,      NONE)
+NVPTX_GPU("sm_121a", SM_121a, "compute_121a", 1210, CUDA_129, NEW,      ACCELERATED)
+NVPTX_GPU("sm_121f", SM_121f, "compute_121f", 1210, CUDA_129, NEW,      FAMILY)
+
+#undef NVPTX_GPU
diff --git a/llvm/include/llvm/TargetParser/NVPTXTargetParser.h b/llvm/include/llvm/TargetParser/NVPTXTargetParser.h
new file mode 100644
index 0000000000000..a49130b99ba76
--- /dev/null
+++ b/llvm/include/llvm/TargetParser/NVPTXTargetParser.h
@@ -0,0 +1,69 @@
+//===-- NVPTXTargetParser.h - Parser for NVPTX target ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGETPARSER_NVPTXTARGETPARSER_H
+#define LLVM_TARGETPARSER_NVPTXTARGETPARSER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cstdint>
+
+namespace llvm {
+namespace NVPTX {
+
+/// GPU kinds supported by the NVPTX target.
+enum GPUKind : uint32_t {
+  GK_NONE = 0,
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  GK_##KIND,
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+};
+
+/// Suffix class of an NVPTX architecture name. Enumerator spellings match the
+/// SUFFIX column tokens in NVPTXTargetParser.def.
+enum class ArchSuffix { NONE, ACCELERATED, FAMILY };
+
+/// Parse \p CPU (e.g. "sm_90") into a GPUKind, or GK_NONE if unrecognized.
+LLVM_ABI GPUKind parseArch(StringRef CPU);
+
+/// Return the canonical processor name (e.g. "sm_90") for \p Kind, or "" if
+/// \p Kind is GK_NONE.
+LLVM_ABI StringRef getArchName(GPUKind Kind);
+
+/// Return the virtual (compute_) arch name (e.g. "compute_90") for \p Kind, or
+/// "" if \p Kind is GK_NONE.
+LLVM_ABI StringRef getVirtualArch(GPUKind Kind);
+
+/// Return the numeric compute-capability id (e.g. sm_90 -> 900) for \p Kind, or
+/// 0 if \p Kind is GK_NONE.
+LLVM_ABI unsigned getSmVersion(GPUKind Kind);
+
+/// Return the suffix class of \p Kind.
+LLVM_ABI ArchSuffix getArchSuffix(GPUKind Kind);
+
+/// Whether \p Kind is an accelerated variant (e.g. sm_90a).
+inline bool isAcceleratedArch(GPUKind Kind) {
+  return getArchSuffix(Kind) == ArchSuffix::ACCELERATED;
+}
+
+/// Whether \p Kind is a family-specific variant (e.g. sm_90f) or accelerated.
+inline bool isFamilySpecificArch(GPUKind Kind) {
+  ArchSuffix S = getArchSuffix(Kind);
+  return S == ArchSuffix::FAMILY || S == ArchSuffix::ACCELERATED;
+}
+
+/// Whether \p Kind supports unified addressing. Unified addressing was
+/// introduced with the Pascal generation (sm_60).
+inline bool supportsUnifiedAddressing(GPUKind Kind) {
+  return getSmVersion(Kind) >= 600;
+}
+
+} // namespace NVPTX
+} // namespace llvm
+
+#endif // LLVM_TARGETPARSER_NVPTXTARGETPARSER_H
diff --git a/llvm/lib/TargetParser/CMakeLists.txt b/llvm/lib/TargetParser/CMakeLists.txt
index 89f54ab6ab7a0..cb45571583d23 100644
--- a/llvm/lib/TargetParser/CMakeLists.txt
+++ b/llvm/lib/TargetParser/CMakeLists.txt
@@ -22,6 +22,7 @@ add_llvm_component_library(LLVMTargetParser
   CSKYTargetParser.cpp
   Host.cpp
   LoongArchTargetParser.cpp
+  NVPTXTargetParser.cpp
   PPCTargetParser.cpp
   RISCVISAInfo.cpp
   RISCVTargetParser.cpp
diff --git a/llvm/lib/TargetParser/NVPTXTargetParser.cpp b/llvm/lib/TargetParser/NVPTXTargetParser.cpp
new file mode 100644
index 0000000000000..c9cf67486fa97
--- /dev/null
+++ b/llvm/lib/TargetParser/NVPTXTargetParser.cpp
@@ -0,0 +1,73 @@
+//===-- NVPTXTargetParser - Parser for NVPTX target ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser for the NVPTX (CUDA) GPU list.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TargetParser/NVPTXTargetParser.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace llvm;
+using namespace NVPTX;
+
+GPUKind llvm::NVPTX::parseArch(StringRef CPU) {
+  return StringSwitch<GPUKind>(CPU)
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  .Case(NAME, GK_##KIND)
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+      .Default(GK_NONE);
+}
+
+StringRef llvm::NVPTX::getArchName(GPUKind Kind) {
+  switch (Kind) {
+  case GK_NONE:
+    return "";
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case GK_##KIND:                                                              \
+    return NAME;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+  }
+  llvm_unreachable("invalid NVPTX GPUKind");
+}
+
+StringRef llvm::NVPTX::getVirtualArch(GPUKind Kind) {
+  switch (Kind) {
+  case GK_NONE:
+    return "";
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case GK_##KIND:                                                              \
+    return VIRTUAL;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+  }
+  llvm_unreachable("invalid NVPTX GPUKind");
+}
+
+unsigned llvm::NVPTX::getSmVersion(GPUKind Kind) {
+  switch (Kind) {
+  case GK_NONE:
+    return 0;
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case GK_##KIND:                                                              \
+    return SM_ID;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+  }
+  llvm_unreachable("invalid NVPTX GPUKind");
+}
+
+ArchSuffix llvm::NVPTX::getArchSuffix(GPUKind Kind) {
+  switch (Kind) {
+  case GK_NONE:
+    return ArchSuffix::NONE;
+#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX)        \
+  case GK_##KIND:                                                              \
+    return ArchSuffix::SUFFIX;
+#include "llvm/TargetParser/NVPTXTargetParser.def"
+  }
+  llvm_unreachable("invalid NVPTX GPUKind");
+}
diff --git a/llvm/unittests/TargetParser/CMakeLists.txt b/llvm/unittests/TargetParser/CMakeLists.txt
index 086c57903716f..cb63202ea8028 100644
--- a/llvm/unittests/TargetParser/CMakeLists.txt
+++ b/llvm/unittests/TargetParser/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(TargetParserTests
   CSKYTargetParserTest.cpp
   Host.cpp
+  NVPTXTargetParserTest.cpp
   RISCVISAInfoTest.cpp
   RISCVTargetParserTest.cpp
   TargetParserTest.cpp
diff --git a/llvm/unittests/TargetParser/NVPTXTargetParserTest.cpp b/llvm/unittests/TargetParser/NVPTXTargetParserTest.cpp
new file mode 100644
index 0000000000000..c5bb7405c569b
--- /dev/null
+++ b/llvm/unittests/TargetParser/NVPTXTargetParserTest.cpp
@@ -0,0 +1,72 @@
+//===----------- NVPTXTargetParserTest.cpp - NVPTX Target Parser ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TargetParser/NVPTXTargetParser.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(NVPTXTargetParserTest, ParseArch) {
+  EXPECT_EQ(NVPTX::parseArch("sm_90"), NVPTX::GK_SM_90);
+  EXPECT_EQ(NVPTX::parseArch("sm_90a"), NVPTX::GK_SM_90a);
+  EXPECT_EQ(NVPTX::parseArch("sm_100f"), NVPTX::GK_SM_100f);
+  // sm_32 uses the underscore-suffixed enumerator internally but the canonical
+  // name has no trailing underscore.
+  EXPECT_EQ(NVPTX::parseArch("sm_32"), NVPTX::GK_SM_32_);
+  EXPECT_EQ(NVPTX::parseArch("gfx900"), NVPTX::GK_NONE);
+  EXPECT_EQ(NVPTX::parseArch(""), NVPTX::GK_NONE);
+}
+
+TEST(NVPTXTargetParserTest, ArchNames) {
+  EXPECT_EQ(NVPTX::getArchName(NVPTX::GK_SM_90), "sm_90");
+  EXPECT_EQ(NVPTX::getArchName(NVPTX::GK_SM_32_), "sm_32");
+  EXPECT_EQ(NVPTX::getVirtualArch(NVPTX::GK_SM_90), "compute_90");
+  // sm_21 shares the compute_20 virtual arch.
+  EXPECT_EQ(NVPTX::getVirtualArch(NVPTX::GK_SM_21), "compute_20");
+  EXPECT_EQ(NVPTX::getArchName(NVPTX::GK_NONE), "");
+  EXPECT_EQ(NVPTX::getVirtualArch(NVPTX::GK_NONE), "");
+}
+
+TEST(NVPTXTargetParserTest, SmVersion) {
+  EXPECT_EQ(NVPTX::getSmVersion(NVPTX::GK_SM_90), 900u);
+  EXPECT_EQ(NVPTX::getSmVersion(NVPTX::GK_SM_90a), 900u);
+  EXPECT_EQ(NVPTX::getSmVersion(NVPTX::GK_SM_100f), 1000u);
+  EXPECT_EQ(NVPTX::getSmVersion(NVPTX::GK_NONE), 0u);
+}
+
+TEST(NVPTXTargetParserTest, ArchSuffix) {
+  EXPECT_FALSE(NVPTX::isAcceleratedArch(NVPTX::GK_SM_90));
+  EXPECT_TRUE(NVPTX::isAcceleratedArch(NVPTX::GK_SM_90a));
+  EXPECT_FALSE(NVPTX::isAcceleratedArch(NVPTX::GK_SM_100f));
+
+  // Family-specific covers both 'f' and 'a' variants.
+  EXPECT_FALSE(NVPTX::isFamilySpecificArch(NVPTX::GK_SM_90));
+  EXPECT_TRUE(NVPTX::isFamilySpecificArch(NVPTX::GK_SM_100f));
+  EXPECT_TRUE(NVPTX::isFamilySpecificArch(NVPTX::GK_SM_90a));
+}
+
+// Every parseable name must round-trip back to the same canonical name.
+TEST(NVPTXTargetParserTest, RoundTrip) {
+  static const char *const Names[] = {
+      "sm_20",   "sm_21",  "sm_30",   "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"};
+  for (const char *Name : Names) {
+    NVPTX::GPUKind Kind = NVPTX::parseArch(Name);
+    EXPECT_NE(Kind, NVPTX::GK_NONE) << Name;
+    EXPECT_EQ(NVPTX::getArchName(Kind), Name);
+  }
+}
+
+} // namespace
diff --git a/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn
index cc548482163d9..8a74590801ff2 100644
--- a/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn
@@ -15,6 +15,7 @@ static_library("TargetParser") {
     "CSKYTargetParser.cpp",
     "Host.cpp",
     "LoongArchTargetParser.cpp",
+    "NVPTXTargetParser.cpp",
     "PPCTargetParser.cpp",
     "RISCVISAInfo.cpp",
     "RISCVTargetParser.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/unittests/TargetParser/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/TargetParser/BUILD.gn
index 8c6ce455f8b35..1f3eae899f0fa 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/TargetParser/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/TargetParser/BUILD.gn
@@ -9,6 +9,7 @@ unittest("TargetParserTests") {
   sources = [
     "CSKYTargetParserTest.cpp",
     "Host.cpp",
+    "NVPTXTargetParserTest.cpp",
     "RISCVISAInfoTest.cpp",
     "RISCVTargetParserTest.cpp",
     "TargetParserTest.cpp",



More information about the cfe-commits mailing list