[flang-commits] [flang] f4225d3 - [AArch64] Reland "Improve TargetParser API"

Tomas Matheson via flang-commits flang-commits at lists.llvm.org
Sat Jan 14 06:44:44 PST 2023


Author: Tomas Matheson
Date: 2023-01-14T14:43:38Z
New Revision: f4225d325c19ae0e5dbe39faa900d81e24559da0

URL: https://github.com/llvm/llvm-project/commit/f4225d325c19ae0e5dbe39faa900d81e24559da0
DIFF: https://github.com/llvm/llvm-project/commit/f4225d325c19ae0e5dbe39faa900d81e24559da0.diff

LOG: [AArch64] Reland "Improve TargetParser API"

Reworked after several other major changes to the TargetParser since
this was reverted. Combined with several other changes.

Inline calls for the following macros and delete AArch64TargetParser.def:
 AARCH64_ARCH,  AARCH64_CPU_NAME,  AARCH64_CPU_ALIAS, AARCH64_ARCH_EXT_NAME

Squashed changes from D139278 and D139102.

Differential Revision: https://reviews.llvm.org/D138792

Added: 
    

Modified: 
    clang/lib/Basic/Targets/AArch64.cpp
    clang/lib/Basic/Targets/AArch64.h
    clang/lib/Driver/ToolChains/Arch/AArch64.cpp
    clang/test/Preprocessor/aarch64-target-features.c
    flang/test/Driver/target-cpu-features.f90
    lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
    llvm/include/llvm/ADT/StringRef.h
    llvm/include/llvm/Support/VersionTuple.h
    llvm/include/llvm/TargetParser/AArch64TargetParser.h
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/TargetParser/AArch64TargetParser.cpp
    llvm/unittests/TargetParser/TargetParserTest.cpp

Removed: 
    llvm/include/llvm/TargetParser/AArch64TargetParser.def


################################################################################
diff  --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index a4b27bb64ab8d..d7893c1139f15 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -47,69 +47,58 @@ static constexpr Builtin::Info BuiltinInfo[] = {
 #include "clang/Basic/BuiltinsAArch64.def"
 };
 
-static StringRef getArchVersionString(llvm::AArch64::ArchKind Kind) {
-  switch (Kind) {
-  case llvm::AArch64::ArchKind::ARMV9A:
-  case llvm::AArch64::ArchKind::ARMV9_1A:
-  case llvm::AArch64::ArchKind::ARMV9_2A:
-  case llvm::AArch64::ArchKind::ARMV9_3A:
-  case llvm::AArch64::ArchKind::ARMV9_4A:
-    return "9";
-  default:
-    return "8";
-  }
-}
-
 void AArch64TargetInfo::setArchFeatures() {
-  switch (ArchKind) {
-  case llvm::AArch64::ArchKind::ARMV8_9A:
-  case llvm::AArch64::ArchKind::ARMV8_8A:
-  case llvm::AArch64::ArchKind::ARMV8_7A:
-    HasWFxT = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_6A:
-    HasBFloat16 = true;
-    HasMatMul = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_5A:
-    HasAlternativeNZCV = true;
-    HasFRInt3264 = true;
-    HasSSBS = true;
-    HasSB = true;
-    HasPredRes = true;
-    HasBTI = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_4A:
+  if (*ArchInfo == llvm::AArch64::ARMV8R) {
     HasDotProd = true;
     HasDIT = true;
     HasFlagM = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_3A:
     HasRCPC = true;
     FPU |= NeonMode;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_2A:
     HasCCPP = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV8_1A:
     HasCRC = true;
     HasLSE = true;
     HasRDM = true;
-    return;
-  default:
-    break;
-  }
-  switch (ArchKind) {
-  case llvm::AArch64::ArchKind::ARMV9_4A:
-  case llvm::AArch64::ArchKind::ARMV9_3A:
-  case llvm::AArch64::ArchKind::ARMV9_2A:
-    HasWFxT = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV9_1A:
-    HasBFloat16 = true;
-    HasMatMul = true;
-    LLVM_FALLTHROUGH;
-  case llvm::AArch64::ArchKind::ARMV9A:
+  } else if (ArchInfo->Version.getMajor() == 8) {
+    if (ArchInfo->Version.getMinor() >= 7) {
+      HasWFxT = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 6) {
+      HasBFloat16 = true;
+      HasMatMul = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 5) {
+      HasAlternativeNZCV = true;
+      HasFRInt3264 = true;
+      HasSSBS = true;
+      HasSB = true;
+      HasPredRes = true;
+      HasBTI = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 4) {
+      HasDotProd = true;
+      HasDIT = true;
+      HasFlagM = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 3) {
+      HasRCPC = true;
+      FPU |= NeonMode;
+    }
+    if (ArchInfo->Version.getMinor() >= 2) {
+      HasCCPP = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 1) {
+      HasCRC = true;
+      HasLSE = true;
+      HasRDM = true;
+    }
+  } else if (ArchInfo->Version.getMajor() == 9) {
+    if (ArchInfo->Version.getMinor() >= 2) {
+      HasWFxT = true;
+    }
+    if (ArchInfo->Version.getMinor() >= 1) {
+      HasBFloat16 = true;
+      HasMatMul = true;
+    }
     FPU |= SveMode;
     HasSVE2 = true;
     HasFullFP16 = true;
@@ -128,29 +117,6 @@ void AArch64TargetInfo::setArchFeatures() {
     HasCRC = true;
     HasLSE = true;
     HasRDM = true;
-    return;
-  default:
-    break;
-  }
-  if (ArchKind == llvm::AArch64::ArchKind::ARMV8R) {
-    HasDotProd = true;
-    HasDIT = true;
-    HasFlagM = true;
-    HasRCPC = true;
-    FPU |= NeonMode;
-    HasCCPP = true;
-    HasCRC = true;
-    HasLSE = true;
-    HasRDM = true;
-  }
-}
-
-StringRef AArch64TargetInfo::getArchProfile() const {
-  switch (ArchKind) {
-  case llvm::AArch64::ArchKind::ARMV8R:
-    return "R";
-  default:
-    return "A";
   }
 }
 
@@ -257,7 +223,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
 
 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
   return Name == "generic" ||
-         llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
+         llvm::AArch64::parseCpu(Name).Arch != llvm::AArch64::INVALID;
 }
 
 bool AArch64TargetInfo::setCPU(const std::string &Name) {
@@ -387,8 +353,10 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
 
   // ACLE predefines. Many can only have one possible value on v8 AArch64.
   Builder.defineMacro("__ARM_ACLE", "200");
-  Builder.defineMacro("__ARM_ARCH", getArchVersionString(ArchKind));
-  Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + getArchProfile() + "'");
+  Builder.defineMacro("__ARM_ARCH",
+                      std::to_string(ArchInfo->Version.getMajor()));
+  Builder.defineMacro("__ARM_ARCH_PROFILE",
+                      std::string("'") + (char)ArchInfo->Profile + "'");
 
   Builder.defineMacro("__ARM_64BIT_STATE", "1");
   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
@@ -559,52 +527,34 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
   if (HasD128)
     Builder.defineMacro("__ARM_FEATURE_SYSREG128", "1");
 
-  switch (ArchKind) {
-  default:
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_1A:
+  if (*ArchInfo == llvm::AArch64::ARMV8_1A)
     getTargetDefinesARMV81A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_2A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_2A)
     getTargetDefinesARMV82A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_3A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_3A)
     getTargetDefinesARMV83A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_4A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_4A)
     getTargetDefinesARMV84A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_5A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_5A)
     getTargetDefinesARMV85A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_6A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_6A)
     getTargetDefinesARMV86A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_7A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_7A)
     getTargetDefinesARMV87A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_8A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_8A)
     getTargetDefinesARMV88A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV8_9A:
+  else if (*ArchInfo == llvm::AArch64::ARMV8_9A)
     getTargetDefinesARMV89A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV9A:
+  else if (*ArchInfo == llvm::AArch64::ARMV9A)
     getTargetDefinesARMV9A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV9_1A:
+  else if (*ArchInfo == llvm::AArch64::ARMV9_1A)
     getTargetDefinesARMV91A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV9_2A:
+  else if (*ArchInfo == llvm::AArch64::ARMV9_2A)
     getTargetDefinesARMV92A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV9_3A:
+  else if (*ArchInfo == llvm::AArch64::ARMV9_3A)
     getTargetDefinesARMV93A(Opts, Builder);
-    break;
-  case llvm::AArch64::ArchKind::ARMV9_4A:
+  else if (*ArchInfo == llvm::AArch64::ARMV9_4A)
     getTargetDefinesARMV94A(Opts, Builder);
-    break;
-  }
 
   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
@@ -645,42 +595,34 @@ AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
 unsigned AArch64TargetInfo::multiVersionSortPriority(StringRef Name) const {
   if (Name == "default")
     return 0;
-  unsigned Priority = llvm::StringSwitch<unsigned>(Name)
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  .Case(NAME, FMV_PRIORITY)
-#include "llvm/TargetParser/AArch64TargetParser.def"
-      ;
-  assert((Name == "none" || Priority < multiVersionFeatureCost()) &&
-         "FMV priority is out of bounds!");
-  return Priority;
+  for (const auto &E : llvm::AArch64::Extensions)
+    if (Name == E.Name)
+      return E.FmvPriority;
+  return 0;
 }
 
 unsigned AArch64TargetInfo::multiVersionFeatureCost() const {
   // Take the maximum priority as per feature cost, so more features win.
-  // AARCH64_ARCH_EXT_NAME "none" feature must have top priority, use it.
-  return multiVersionSortPriority("none");
+  return llvm::AArch64::ExtensionInfo::MaxFMVPriority;
 }
 
 bool AArch64TargetInfo::getFeatureDepOptions(StringRef Name,
                                              std::string &FeatureVec) const {
-  FeatureVec = llvm::StringSwitch<std::string>(Name)
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  .Case(NAME, DEP_FEATURES)
-#include "llvm/TargetParser/AArch64TargetParser.def"
-                   .Default("");
+  FeatureVec = "";
+  for (const auto &E : llvm::AArch64::Extensions) {
+    if (Name == E.Name) {
+      FeatureVec = E.DependentFeatures;
+      break;
+    }
+  }
   return FeatureVec != "";
 }
 
 bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
-  unsigned Feat = llvm::StringSwitch<unsigned>(FeatureStr)
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  .Case(NAME, llvm::AArch64::FEAT_##FMV_ID)
-#include "llvm/TargetParser/AArch64TargetParser.def"
-                      .Default(llvm::AArch64::FEAT_MAX);
-  return Feat != llvm::AArch64::FEAT_MAX;
+  for (const auto &E : llvm::AArch64::Extensions)
+    if (FeatureStr == E.Name)
+      return true;
+  return false;
 }
 
 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
@@ -736,24 +678,21 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
 void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
                                           StringRef Name, bool Enabled) const {
   Features[Name] = Enabled;
-
   // If the feature is an architecture feature (like v8.2a), add all previous
   // architecture versions and any dependant target features.
-  llvm::AArch64::ArchKind AK = llvm::AArch64::getSubArchArchKind(Name);
-  if (AK == llvm::AArch64::ArchKind::INVALID)
-    return;
-  // In case of v9.x the v8.x counterparts are added too.
-  if ("9" == getArchVersionString(AK))
-    for (llvm::AArch64::ArchKind I = llvm::AArch64::convertV9toV8(AK);
-         I != llvm::AArch64::ArchKind::INVALID; --I)
-      Features[llvm::AArch64::getSubArch(I)] = Enabled;
-
-  llvm::AArch64::ArchKind I = AK;
-  for (--I; I != llvm::AArch64::ArchKind::INVALID; --I)
-    Features[llvm::AArch64::getSubArch(I)] = Enabled;
+  const llvm::AArch64::ArchInfo &ArchInfo =
+      llvm::AArch64::ArchInfo::findBySubArch(Name);
+
+  if (ArchInfo == llvm::AArch64::INVALID)
+    return; // Not an architecure, nothing more to do.
+
+  for (const auto *OtherArch : llvm::AArch64::ArchInfos)
+    if (ArchInfo.implies(*OtherArch))
+      Features[OtherArch->getSubArch()] = Enabled;
 
   // Set any features implied by the architecture
-  uint64_t Extensions = llvm::AArch64::getDefaultExtensions("generic", AK);
+  uint64_t Extensions =
+      llvm::AArch64::getDefaultExtensions("generic", ArchInfo);
   std::vector<StringRef> CPUFeats;
   if (llvm::AArch64::getExtensionFeatures(Extensions, CPUFeats)) {
     for (auto F : CPUFeats) {
@@ -899,38 +838,51 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
     if (Feature == "+strict-align")
       HasUnaligned = false;
     // All predecessor archs are added but select the latest one for ArchKind.
-    if (Feature == "+v8a" && ArchKind < llvm::AArch64::ArchKind::ARMV8A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8A;
-    if (Feature == "+v8.1a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_1A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
-    if (Feature == "+v8.2a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_2A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
-    if (Feature == "+v8.3a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_3A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
-    if (Feature == "+v8.4a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_4A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
-    if (Feature == "+v8.5a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_5A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
-    if (Feature == "+v8.6a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_6A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
-    if (Feature == "+v8.7a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_7A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
-    if (Feature == "+v8.8a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_8A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_8A;
-    if (Feature == "+v8.9a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_9A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV8_9A;
-    if (Feature == "+v9a" && ArchKind < llvm::AArch64::ArchKind::ARMV9A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV9A;
-    if (Feature == "+v9.1a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_1A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV9_1A;
-    if (Feature == "+v9.2a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_2A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV9_2A;
-    if (Feature == "+v9.3a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_3A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV9_3A;
-    if (Feature == "+v9.4a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_4A)
-      ArchKind = llvm::AArch64::ArchKind::ARMV9_4A;
+    if (Feature == "+v8a" && ArchInfo->Version < llvm::AArch64::ARMV8A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8A;
+    if (Feature == "+v8.1a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_1A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_1A;
+    if (Feature == "+v8.2a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_2A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_2A;
+    if (Feature == "+v8.3a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_3A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_3A;
+    if (Feature == "+v8.4a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_4A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_4A;
+    if (Feature == "+v8.5a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_5A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_5A;
+    if (Feature == "+v8.6a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_6A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_6A;
+    if (Feature == "+v8.7a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_7A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_7A;
+    if (Feature == "+v8.8a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_8A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_8A;
+    if (Feature == "+v8.9a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV8_9A.Version)
+      ArchInfo = &llvm::AArch64::ARMV8_9A;
+    if (Feature == "+v9a" && ArchInfo->Version < llvm::AArch64::ARMV9A.Version)
+      ArchInfo = &llvm::AArch64::ARMV9A;
+    if (Feature == "+v9.1a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV9_1A.Version)
+      ArchInfo = &llvm::AArch64::ARMV9_1A;
+    if (Feature == "+v9.2a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV9_2A.Version)
+      ArchInfo = &llvm::AArch64::ARMV9_2A;
+    if (Feature == "+v9.3a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV9_3A.Version)
+      ArchInfo = &llvm::AArch64::ARMV9_3A;
+    if (Feature == "+v9.4a" &&
+        ArchInfo->Version < llvm::AArch64::ARMV9_4A.Version)
+      ArchInfo = &llvm::AArch64::ARMV9_4A;
     if (Feature == "+v8r")
-      ArchKind = llvm::AArch64::ArchKind::ARMV8R;
+      ArchInfo = &llvm::AArch64::ARMV8R;
     if (Feature == "+fullfp16") {
       FPU |= NeonMode;
       HasFullFP16 = true;
@@ -998,8 +950,8 @@ bool AArch64TargetInfo::initFeatureMap(
     const std::vector<std::string> &FeaturesVec) const {
   std::vector<std::string> UpdatedFeaturesVec;
   // Parse the CPU and add any implied features.
-  llvm::AArch64::ArchKind Arch = llvm::AArch64::parseCPUArch(CPU);
-  if (Arch != llvm::AArch64::ArchKind::INVALID) {
+  const llvm::AArch64::ArchInfo &Arch = llvm::AArch64::parseCpu(CPU).Arch;
+  if (Arch != llvm::AArch64::INVALID) {
     uint64_t Exts = llvm::AArch64::getDefaultExtensions(CPU, Arch);
     std::vector<StringRef> CPUFeats;
     llvm::AArch64::getExtensionFeatures(Exts, CPUFeats);
@@ -1082,13 +1034,13 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
       FoundArch = true;
       std::pair<StringRef, StringRef> Split =
           Feature.split("=").second.trim().split("+");
-      llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
+      const llvm::AArch64::ArchInfo &AI = llvm::AArch64::parseArch(Split.first);
 
       // Parse the architecture version, adding the required features to
       // Ret.Features.
-      if (ArchKind == llvm::AArch64::ArchKind::INVALID)
+      if (AI == llvm::AArch64::INVALID)
         continue;
-      Ret.Features.push_back(llvm::AArch64::getArchFeature(ArchKind).str());
+      Ret.Features.push_back(AI.ArchFeature.str());
       // Add any extra features, after the +
       SplitAndAddFeatures(Split.second, Ret.Features);
     } else if (Feature.startswith("cpu=")) {

diff  --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 55e8a63766747..95edf6995f9e4 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -76,10 +76,9 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
   bool HasNoSVE = false;
   bool HasFMV = true;
 
-  llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::INVALID;
+  const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A;
 
   std::string ABI;
-  StringRef getArchProfile() const;
 
 public:
   AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);

diff  --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 2a1269316bc75..fcbf2e08d12df 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -70,7 +70,7 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
 // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
 static bool DecodeAArch64Features(const Driver &D, StringRef text,
                                   std::vector<StringRef> &Features,
-                                  llvm::AArch64::ArchKind ArchKind) {
+                                  const llvm::AArch64::ArchInfo &ArchInfo) {
   SmallVector<StringRef, 8> Split;
   text.split(Split, StringRef("+"), -1, false);
 
@@ -104,14 +104,14 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
 
     // +sve implies +f32mm if the base architecture is >= v8.6A (except v9A)
     // It isn't the case in general that sve implies both f64mm and f32mm
-    if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV8_7A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV8_8A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV8_9A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV9_2A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV9_3A ||
-         ArchKind == llvm::AArch64::ArchKind::ARMV9_4A) &&
+    if ((ArchInfo == llvm::AArch64::ARMV8_6A ||
+         ArchInfo == llvm::AArch64::ARMV8_7A ||
+         ArchInfo == llvm::AArch64::ARMV8_8A ||
+         ArchInfo == llvm::AArch64::ARMV8_9A ||
+         ArchInfo == llvm::AArch64::ARMV9_1A ||
+         ArchInfo == llvm::AArch64::ARMV9_2A ||
+         ArchInfo == llvm::AArch64::ARMV9_3A ||
+         ArchInfo == llvm::AArch64::ARMV9_4A) &&
         Feature == "sve")
       Features.push_back("+f32mm");
   }
@@ -123,10 +123,8 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
 static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
                               std::vector<StringRef> &Features) {
   std::pair<StringRef, StringRef> Split = Mcpu.split("+");
-  CPU = Split.first;
-  llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::ARMV8A;
-
-  CPU = llvm::AArch64::resolveCPUAlias(CPU);
+  const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A;
+  CPU = llvm::AArch64::resolveCPUAlias(Split.first);
 
   if (CPU == "native")
     CPU = llvm::sys::getHostCPUName();
@@ -134,21 +132,21 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
   if (CPU == "generic") {
     Features.push_back("+neon");
   } else {
-    ArchKind = llvm::AArch64::parseCPUArch(CPU);
-    if (ArchKind == llvm::AArch64::ArchKind::INVALID)
+    ArchInfo = &llvm::AArch64::parseCpu(CPU).Arch;
+    if (*ArchInfo == llvm::AArch64::INVALID)
       return false;
-    Features.push_back(llvm::AArch64::getArchFeature(ArchKind));
+    Features.push_back(ArchInfo->ArchFeature);
 
-    uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
+    uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, *ArchInfo);
     if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
       return false;
-   }
+  }
 
-   if (Split.second.size() &&
-       !DecodeAArch64Features(D, Split.second, Features, ArchKind))
-     return false;
+  if (Split.second.size() &&
+      !DecodeAArch64Features(D, Split.second, Features, *ArchInfo))
+    return false;
 
-   return true;
+  return true;
 }
 
 static bool
@@ -158,25 +156,26 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
   std::string MarchLowerCase = March.lower();
   std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
 
-  llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
+  const llvm::AArch64::ArchInfo *ArchInfo =
+      &llvm::AArch64::parseArch(Split.first);
   if (Split.first == "native")
-    ArchKind = llvm::AArch64::getCPUArchKind(llvm::sys::getHostCPUName().str());
-  if (ArchKind == llvm::AArch64::ArchKind::INVALID)
+    ArchInfo = &llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
+  if (*ArchInfo == llvm::AArch64::INVALID)
     return false;
-  Features.push_back(llvm::AArch64::getArchFeature(ArchKind));
+  Features.push_back(ArchInfo->ArchFeature);
 
   // Enable SVE2 by default on Armv9-A.
   // It can still be disabled if +nosve2 is present.
   // We must do this early so that DecodeAArch64Features has the correct state
-  if ((ArchKind == llvm::AArch64::ArchKind::ARMV9A ||
-       ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
-       ArchKind == llvm::AArch64::ArchKind::ARMV9_2A)) {
+  if ((*ArchInfo == llvm::AArch64::ARMV9A ||
+       *ArchInfo == llvm::AArch64::ARMV9_1A ||
+       *ArchInfo == llvm::AArch64::ARMV9_2A)) {
     Features.push_back("+sve");
     Features.push_back("+sve2");
   }
 
   if ((Split.second.size() &&
-       !DecodeAArch64Features(D, Split.second, Features, ArchKind)))
+       !DecodeAArch64Features(D, Split.second, Features, *ArchInfo)))
     return false;
 
   return true;

diff  --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c
index 3ec31e1024a6c..8ad5b3a91c4d6 100644
--- a/clang/test/Preprocessor/aarch64-target-features.c
+++ b/clang/test/Preprocessor/aarch64-target-features.c
@@ -295,29 +295,29 @@
 // RUN: %clang -target aarch64 -mcpu=a64fx -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A64FX %s
 // RUN: %clang -target aarch64 -mcpu=carmel -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-CARMEL %s
 // CHECK-MCPU-APPLE-A7: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A10: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+crc" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A11: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A12: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.3a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-APPLE-A10: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-APPLE-A11: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-APPLE-A12: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.3a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
 // CHECK-MCPU-A34: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A13: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.4a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fp16fml" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+fullfp16" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-APPLE-A13: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.4a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+fullfp16" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
 // CHECK-MCPU-A35: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
 // CHECK-MCPU-A53: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
 // CHECK-MCPU-A57: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
 // CHECK-MCPU-A72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
 // CHECK-MCPU-CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
-// CHECK-MCPU-CORTEX-R82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8r" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fp16fml" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+ssbs" "-target-feature" "+sb" "-target-feature" "+fullfp16"
+// CHECK-MCPU-CORTEX-R82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8r" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+neon" "-target-feature" "+ssbs" "-target-feature" "+fullfp16"
 // CHECK-MCPU-M3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
-// CHECK-MCPU-M4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16"
+// CHECK-MCPU-M4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+sha2" "-target-feature" "+aes"
 // CHECK-MCPU-KRYO: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
-// CHECK-MCPU-THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon"
-// CHECK-MCPU-A64FX: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+sve" "-target-feature" "+sha2"
-// CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.1a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-A64FX: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+sve" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+sha2" "-target-feature" "+aes"
 
 // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s
-// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+v8.5a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fp16fml" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+fullfp16" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+v8.5a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+fullfp16" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
 
 // RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s
-// CHECK-ARCH-ARM64_32: "-target-cpu" "apple-s4" "-target-feature" "+v8.3a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-ARCH-ARM64_32: "-target-cpu" "apple-s4" "-target-feature" "+v8.3a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
 
 // RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s
 // RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s

diff  --git a/flang/test/Driver/target-cpu-features.f90 b/flang/test/Driver/target-cpu-features.f90
index 985a13de75952..027044869ffae 100644
--- a/flang/test/Driver/target-cpu-features.f90
+++ b/flang/test/Driver/target-cpu-features.f90
@@ -36,7 +36,7 @@
 ! CHECK-A57-SAME: "-target-cpu" "cortex-a57" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+sha2" "-target-feature" "+aes"
 
 ! CHECK-A76: "-fc1" "-triple" "aarch64-unknown-linux-gnu"
-! CHECK-A76-SAME: "-target-cpu" "cortex-a76" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+ssbs" "-target-feature" "+sha2" "-target-feature" "+aes"
+! CHECK-A76-SAME: "-target-cpu" "cortex-a76" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+neon" "-target-feature" "+ssbs" "-target-feature" "+sha2" "-target-feature" "+aes"
 
 ! CHECK-ARMV9: "-fc1" "-triple" "aarch64-unknown-linux-gnu"
 ! CHECK-ARMV9-SAME: "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9a" "-target-feature" "+sve" "-target-feature" "+sve2"

diff  --git a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
index 480ed6b8e9d75..e154f544e7cc6 100644
--- a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
+++ b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
@@ -9,98 +9,111 @@
 .globl  fn
 .type   fn, @function
 fn:
-  // These are in the same order as llvm/include/llvm/TargetParser/AArch64TargetParser.def
-  crc32b w0, w0, w0                   // CRC
-  ldaddab w0, w0, [sp]                // LSE
-  sqrdmlah v0.4h, v1.4h, v2.4h        // RDM
-  // CRYPTO enables a combination of other features
-  sm4e v0.4s, v0.4s                   // SM4
-  bcax v0.16b, v0.16b, v0.16b, v0.16b // SHA3
-  sha256h q0, q0, v0.4s               // SHA256
-  aesd v0.16b, v0.16b                 // AES
-  sdot v0.2s, v1.8b, v2.8b            // DOTPROD
-  fcvt d0, s0                         // FP
-  addp v0.4s, v0.4s, v0.4s            // SIMD (neon)
-  fabs h1, h2                         // FP16
-  fmlal v0.2s, v1.2h, v2.2h           // FP16FML
-  psb csync                           // PROFILE/SPE
-  msr erxpfgctl_el1, x0               // RAS
-  abs z31.h, p7/m, z31.h              // SVE
-  sqdmlslbt z0.d, z1.s, z31.s         // SVE2
-  aesd z0.b, z0.b, z31.b              // SVE2AES
-  sm4e z0.s, z0.s, z0.s               // SVE2SM4
-  rax1 z0.d, z0.d, z0.d               // SVE2SHA3
-  bdep z0.b, z1.b, z31.b              // SVE2BITPERM
-  addqv   v0.8h, p0, z0.h             // SVE2p1 / SME2p1
-  bfadd z23.h, p3/m, z23.h, z13.h     // B16B16
-  ldaprb w0, [x0, #0]                 // RCPC
-  mrs x0, rndr                        // RAND
-  irg x0, x0                          // MTE
-  mrs x2, ssbs                        // SSBS
-  sb                                  // SB
-  cfp rctx, x0                        // PREDRES
-  bfdot v2.2s, v3.4h, v4.4h           // BF16
-  smmla v1.4s, v16.16b, v31.16b       // I8MM
-  fmmla z0.s, z1.s, z2.s              // F32MM
-  fmmla z0.d, z1.d, z2.d              // F64MM
-  tcommit                             // TME
-  ld64b x0, [x13]                     // LS64
-  brb iall                            // BRBE
-  pacia x0, x1                        // PAUTH
-  cfinv                               // FLAGM
-  addha za0.s, p0/m, p0/m, z0.s       // SME
-  fmopa za0.d, p0/m, p0/m, z0.d, z0.d // SMEF64
-  addha za0.d, p0/m, p0/m, z0.d       // SMEI64
-  add {z0.h, z1.h}, {z0.h, z1.h}, z0.h // SME2
+  // These are in alphabetical order by extension name
+  aesd v0.16b, v0.16b                   // AEK_AES
+  bfadd z23.h, p3/m, z23.h, z13.h       // AEK_B16B16
+  bfdot v2.2s, v3.4h, v4.4h             // AEK_BF16
+  brb iall                              // AEK_BRBE
+  crc32b w0, w0, w0                     // AEK_CRC
+  // AEK_CRYPTO enables a combination of other features
+  smin x0, x0, #0                       // AEK_CSSC
+  sysp	#0, c2, c0, #0, x0, x1          // AEK_D128
+  sdot v0.2s, v1.8b, v2.8b              // AEK_DOTPROD
+  fmmla z0.s, z1.s, z2.s                // AEK_F32MM
+  fmmla z0.d, z1.d, z2.d                // AEK_F64MM
+  cfinv                                 // AEK_FLAGM
+  fcvt d0, s0                           // AEK_FP
+  fabs h1, h2                           // AEK_FP16
+  fmlal v0.2s, v1.2h, v2.2h             // AEK_FP16FML
+  bc.eq lbl                             // AEK_HBC
+  smmla v1.4s, v16.16b, v31.16b         // AEK_I8MM
+  ld64b x0, [x13]                       // AEK_LS64
+  ldaddab w0, w0, [sp]                  // AEK_LSE
+  ldclrp x1, x2, [x11]                  // AEK_LSE128
+  irg x0, x0                            // AEK_MTE
+  cpyfp [x0]!, [x1]!, x2!               // AEK_MOPS
+  pacia x0, x1                          // AEK_PAUTH
+  mrs x0, pmccntr_el0                   // AEK_PERFMON
+  cfp rctx, x0                          // AEK_PREDRES
+  psb csync                             // AEK_PROFILE/SPE
+  msr erxpfgctl_el1, x0                 // AEK_RAS
+  ldaprb w0, [x0, #0]                   // AEK_RCPC
+  stilp w26, w2, [x18]                  // AEK_RCPC3
+  sqrdmlah v0.4h, v1.4h, v2.4h          // AEK_RDM
+  mrs x0, rndr                          // AEK_RAND
+  sb                                    // AEK_SB
+  sha256h q0, q0, v0.4s                 // AEK_SHA2
+  bcax v0.16b, v0.16b, v0.16b, v0.16b   // AEK_SHA3
+  addp v0.4s, v0.4s, v0.4s              // AEK_SIMD (neon)
+  sm4e v0.4s, v0.4s                     // AEK_SM4
+  addha za0.s, p0/m, p0/m, z0.s         // AEK_SME
+  fadd za.h[w11, 7], {z12.h - z13.h}    // AEK_SMEF16F16
+  fmopa za0.d, p0/m, p0/m, z0.d, z0.d   // AEK_SMEF64F64
+  addha za0.d, p0/m, p0/m, z0.d         // AEK_SMEI16I64
+  add {z0.h, z1.h}, {z0.h, z1.h}, z0.h  // AEK_SME2
+  // AEK_SME2P1: see AEK_SVE2P1
+  mrs x2, ssbs                          // AEK_SSBS
+  abs z31.h, p7/m, z31.h                // AEK_SVE
+  sqdmlslbt z0.d, z1.s, z31.s           // AEK_SVE2
+  aesd z0.b, z0.b, z31.b                // AEK_SVE2AES
+  bdep z0.b, z1.b, z31.b                // AEK_SVE2BITPERM
+  rax1 z0.d, z0.d, z0.d                 // AEK_SVE2SHA3
+  sm4e z0.s, z0.s, z0.s                 // AEK_SVE2SM4
+  addqv   v0.8h, p0, z0.h               // AEK_SVE2p1 / AEK_SME2p1
+  rcwswp x0, x1, [x2]                   // AEK_THE
+  tcommit                               // AEK_TME
 lbl:
-  bc.eq lbl                           // HBC
-  cpyfp [x0]!, [x1]!, x2!             // MOPS
-  mrs x0, pmccntr_el0                 // PERFMON
 .fn_end:
   .size   fn, .fn_end-fn
 
 # CHECK: command-disassemble-aarch64-extensions.s.tmp`fn:
-# CHECK: crc32b w0, w0, w0
-# CHECK: ldaddab w0, w0, [sp]
-# CHECK: sqrdmlah v0.4h, v1.4h, v2.4h
-# CHECK: sm4e   v0.4s, v0.4s
-# CHECK: bcax   v0.16b, v0.16b, v0.16b, v0.16b
-# CHECK: sha256h q0, q0, v0.4s
-# CHECK: aesd   v0.16b, v0.16b
-# CHECK: sdot   v0.2s, v1.8b, v2.8b
-# CHECK: fcvt   d0, s0
-# CHECK: addp   v0.4s, v0.4s, v0.4s
-# CHECK: fabs   h1, h2
-# CHECK: fmlal  v0.2s, v1.2h, v2.2h
-# CHECK: psb    csync
-# CHECK: msr    ERXPFGCTL_EL1, x0
-# CHECK: abs    z31.h, p7/m, z31.h
-# CHECK: sqdmlslbt z0.d, z1.s, z31.s
-# CHECK: aesd   z0.b, z0.b, z31.b
-# CHECK: sm4e   z0.s, z0.s, z0.s
-# CHECK: rax1   z0.d, z0.d, z0.d
-# CHECK: bdep   z0.b, z1.b, z31.b
-# CHECK: addqv  v0.8h, p0, z0.h
-# CHECK: bfadd  z23.h, p3/m, z23.h, z13.h
-# CHECK: ldaprb w0, [x0]
-# CHECK: mrs    x0, RNDR
-# CHECK: irg    x0, x0
-# CHECK: mrs    x2, SSBS
-# CHECK: sb
-# CHECK: cfp    rctx, x0
-# CHECK: bfdot  v2.2s, v3.4h, v4.4h
-# CHECK: smmla  v1.4s, v16.16b, v31.16b
-# CHECK: fmmla  z0.s, z1.s, z2.s
-# CHECK: fmmla  z0.d, z1.d, z2.d
-# CHECK: tcommit
-# CHECK: ld64b  x0, [x13]
-# CHECK: brb    iall
-# CHECK: pacia  x0, x1
-# CHECK: cfinv
-# CHECK: addha  za0.s, p0/m, p0/m, z0.s
-# CHECK: fmopa  za0.d, p0/m, p0/m, z0.d, z0.d
-# CHECK: addha  za0.d, p0/m, p0/m, z0.d
-# CHECK: add    { z0.h, z1.h }, { z0.h, z1.h }, z0.h
-# CHECK: bc.eq  0xa4
-# CHECK: cpyfp  [x0]!, [x1]!, x2!
-# CHECK: mrs    x0, PMCCNTR_EL0
+# CHECK-NEXT: aesd   v0.16b, v0.16b
+# CHECK-NEXT: bfadd  z23.h, p3/m, z23.h, z13.h
+# CHECK-NEXT: bfdot  v2.2s, v3.4h, v4.4h
+# CHECK-NEXT: brb    iall
+# CHECK-NEXT: crc32b w0, w0, w0
+# CHECK-NEXT: smin   x0, x0, #0
+# CHECK-NEXT: sysp   #0x0, c2, c0, #0x0, x0, x1
+# CHECK-NEXT: sdot   v0.2s, v1.8b, v2.8b
+# CHECK-NEXT: fmmla  z0.s, z1.s, z2.s
+# CHECK-NEXT: fmmla  z0.d, z1.d, z2.d
+# CHECK-NEXT: cfinv
+# CHECK-NEXT: fcvt   d0, s0
+# CHECK-NEXT: fabs   h1, h2
+# CHECK-NEXT: fmlal  v0.2s, v1.2h, v2.2h
+# CHECK-NEXT: bc.eq 0xc8
+# CHECK-NEXT: smmla  v1.4s, v16.16b, v31.16b
+# CHECK-NEXT: ld64b  x0, [x13]
+# CHECK-NEXT: ldaddab w0, w0, [sp]
+# CHECK-NEXT: ldclrp  x1, x2, [x11]
+# CHECK-NEXT: irg    x0, x0
+# CHECK-NEXT: cpyfp  [x0]!, [x1]!, x2!
+# CHECK-NEXT: pacia  x0, x1
+# CHECK-NEXT: mrs    x0, PMCCNTR_EL0
+# CHECK-NEXT: cfp    rctx, x0
+# CHECK-NEXT: psb    csync
+# CHECK-NEXT: msr    ERXPFGCTL_EL1, x0
+# CHECK-NEXT: ldaprb w0, [x0]
+# CHECK-NEXT: stilp w26, w2, [x18]
+# CHECK-NEXT: sqrdmlah v0.4h, v1.4h, v2.4h
+# CHECK-NEXT: mrs    x0, RNDR
+# CHECK-NEXT: sb
+# CHECK-NEXT: sha256h q0, q0, v0.4s
+# CHECK-NEXT: bcax   v0.16b, v0.16b, v0.16b, v0.16b
+# CHECK-NEXT: addp   v0.4s, v0.4s, v0.4s
+# CHECK-NEXT: sm4e   v0.4s, v0.4s
+# CHECK-NEXT: addha  za0.s, p0/m, p0/m, z0.s
+# CHECK-NEXT: fadd   za.h[w11, 7, vgx2], { z12.h, z13.h }
+# CHECK-NEXT: fmopa  za0.d, p0/m, p0/m, z0.d, z0.d
+# CHECK-NEXT: addha  za0.d, p0/m, p0/m, z0.d
+# CHECK-NEXT: add    { z0.h, z1.h }, { z0.h, z1.h }, z0.h
+# CHECK-NEXT: mrs    x2, SSBS
+# CHECK-NEXT: abs    z31.h, p7/m, z31.h
+# CHECK-NEXT: sqdmlslbt z0.d, z1.s, z31.s
+# CHECK-NEXT: aesd   z0.b, z0.b, z31.b
+# CHECK-NEXT: bdep   z0.b, z1.b, z31.b
+# CHECK-NEXT: rax1   z0.d, z0.d, z0.d
+# CHECK-NEXT: sm4e   z0.s, z0.s, z0.s
+# CHECK-NEXT: addqv  v0.8h, p0, z0.h
+# CHECK-NEXT: rcwswp x0, x1, [x2]
+# CHECK-NEXT: tcommit

diff  --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index 032f42a51ec0b..9fea390c2ed32 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -561,7 +561,8 @@ namespace llvm {
     /// \param N The number of characters to included in the substring. If N
     /// exceeds the number of characters remaining in the string, the string
     /// suffix (starting with \p Start) will be returned.
-    [[nodiscard]] StringRef substr(size_t Start, size_t N = npos) const {
+    [[nodiscard]] constexpr StringRef substr(size_t Start,
+                                             size_t N = npos) const {
       Start = std::min(Start, Length);
       return StringRef(Data + Start, std::min(N, Length - Start));
     }

diff  --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h
index 1118754f7fd46..828a6db54708d 100644
--- a/llvm/include/llvm/Support/VersionTuple.h
+++ b/llvm/include/llvm/Support/VersionTuple.h
@@ -41,24 +41,25 @@ class VersionTuple {
   unsigned HasBuild : 1;
 
 public:
-  VersionTuple()
+  constexpr VersionTuple()
       : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
         Build(0), HasBuild(false) {}
 
-  explicit VersionTuple(unsigned Major)
+  explicit constexpr VersionTuple(unsigned Major)
       : Major(Major), Minor(0), HasMinor(false), Subminor(0),
         HasSubminor(false), Build(0), HasBuild(false) {}
 
-  explicit VersionTuple(unsigned Major, unsigned Minor)
+  explicit constexpr VersionTuple(unsigned Major, unsigned Minor)
       : Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
         HasSubminor(false), Build(0), HasBuild(false) {}
 
-  explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
+  explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
+                                  unsigned Subminor)
       : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
         HasSubminor(true), Build(0), HasBuild(false) {}
 
-  explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
-                        unsigned Build)
+  explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
+                                  unsigned Subminor, unsigned Build)
       : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
         HasSubminor(true), Build(Build), HasBuild(true) {}
 

diff  --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.def b/llvm/include/llvm/TargetParser/AArch64TargetParser.def
deleted file mode 100644
index 570172ace990a..0000000000000
--- a/llvm/include/llvm/TargetParser/AArch64TargetParser.def
+++ /dev/null
@@ -1,434 +0,0 @@
-//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- 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 provides defines to build up the AARCH64 target parser's logic.
-//
-//===----------------------------------------------------------------------===//
-
-// NOTE: NO INCLUDE GUARD DESIRED!
-
-#ifndef AARCH64_ARCH
-#define AARCH64_ARCH(NAME, ID, ARCH_FEATURE, ARCH_BASE_EXT)
-#endif
-// NOTE: The order and the grouping of the elements matter to make ArchKind iterable.
-// List is organised as armv8a -> armv8n-a, armv9a -> armv9m-a and armv8-r.
-AARCH64_ARCH("invalid", INVALID, "+",
-             AArch64::AEK_NONE)
-AARCH64_ARCH("armv8-a", ARMV8A, "+v8a",
-             (AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD))
-AARCH64_ARCH("armv8.1-a", ARMV8_1A, "+v8.1a",
-             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RDM))
-AARCH64_ARCH("armv8.2-a", ARMV8_2A, "+v8.2a",
-             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM))
-AARCH64_ARCH("armv8.3-a", ARMV8_3A, "+v8.3a",
-             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC))
-AARCH64_ARCH("armv8.4-a", ARMV8_4A, "+v8.4a",
-             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
-AARCH64_ARCH("armv8.5-a", ARMV8_5A, "+v8.5a",
-             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
-AARCH64_ARCH("armv8.6-a", ARMV8_6A, "+v8.6a",
-             (AArch64::AEK_CRC  | AArch64::AEK_FP   |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS  | AArch64::AEK_LSE     |
-              AArch64::AEK_RDM  | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_SM4  | AArch64::AEK_SHA3 | AArch64::AEK_BF16    |
-              AArch64::AEK_SHA2 | AArch64::AEK_AES  | AArch64::AEK_I8MM))
-AARCH64_ARCH("armv8.7-a", ARMV8_7A, "+v8.7a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
-              AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM))
-AARCH64_ARCH("armv8.8-a", ARMV8_8A, "+v8.8a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
-              AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM))
-AARCH64_ARCH("armv8.9-a", ARMV8_9A, "+v8.9a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
-              AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM |
-              AArch64::AEK_RASv2))
-AARCH64_ARCH("armv9-a",   ARMV9A, "+v9a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_SVE | AArch64::AEK_SVE2))
-AARCH64_ARCH("armv9.1-a", ARMV9_1A, "+v9.1a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE |
-              AArch64::AEK_SVE2))
-AARCH64_ARCH("armv9.2-a", ARMV9_2A, "+v9.2a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE |
-              AArch64::AEK_SVE2))
-AARCH64_ARCH("armv9.3-a", ARMV9_3A, "+v9.3a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE |
-              AArch64::AEK_SVE2))
-AARCH64_ARCH("armv9.4-a", ARMV9_4A, "+v9.4a",
-             (AArch64::AEK_CRC | AArch64::AEK_FP |
-              AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
-              AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-              AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE |
-              AArch64::AEK_SVE2 | AArch64::AEK_RASv2))
-// For v8-R, we do not enable crypto and align with GCC that enables a more
-// minimal set of optional architecture extensions.
-AARCH64_ARCH("armv8-r", ARMV8R, "+v8r",
-             (AArch64::AEK_CRC     | AArch64::AEK_RDM  | AArch64::AEK_SSBS |
-              AArch64::AEK_DOTPROD | AArch64::AEK_FP   | AArch64::AEK_SIMD |
-              AArch64::AEK_FP16    | AArch64::AEK_FP16FML | AArch64::AEK_RAS |
-              AArch64::AEK_RCPC    | AArch64::AEK_SB))
-#undef AARCH64_ARCH
-
-#ifndef AARCH64_ARCH_EXT_NAME
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE,\
-                              FMV_ID, DEP_FEATURES, FMV_PRIORITY)
-#endif
-// FIXME: This would be nicer were it tablegen
-AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, {}, {}, MAX, "", 0)
-// "none" feature has the maximum allowed function multi versioning priority
-AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, {}, {}, MAX, "", 1000)
-AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc", CRC, "+crc", 110)
-AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse", LSE, "+lse", 80)
-AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm", RDM,
-                      "+rdm,+fp-armv8,+neon", 70)
-AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto", "-crypto", MAX,
-                      "", 0)
-AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4", SM4,
-                      "+sm4,+fp-armv8,+neon", 60)
-AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3", SHA3,
-                      "+sha3,+sha2,+fp-armv8,+neon", 140)
-AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2", SHA2,
-                      "+sha2,+fp-armv8,+neon", 130)
-AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes", AES,
-                      "+fp-armv8,+neon", 150)
-AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod", "-dotprod",
-                      DOTPROD, "+dotprod,+fp-armv8,+neon", 50)
-AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8", FP,
-                      "+fp-armv8,+neon", 90)
-AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon", SIMD,
-                      "+fp-armv8,+neon", 100)
-AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16", FP16,
-                      "+fullfp16,+fp-armv8,+neon", 170)
-AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml",
-                      FP16FML, "+fp16fml,+fullfp16,+fp-armv8,+neon", 40)
-AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe", MAX, "",
-                      0)
-AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("rasv2", AArch64::AEK_RASv2, "+rasv2", "-rasv2", MAX, "",
-                      0)
-AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve", SVE,
-                      "+sve,+fullfp16,+fp-armv8,+neon", 310)
-AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2", SVE2,
-                      "+sve2,+sve,+fullfp16,+fp-armv8,+neon", 370)
-AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes",
-                      "-sve2-aes", SVE_AES,
-                      "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 380)
-AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4",
-                      "-sve2-sm4", SVE_SM4,
-                      "+sve2,+sve,+sve2-sm4,+fullfp16,+fp-armv8,+neon", 420)
-AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3",
-                      "-sve2-sha3", SVE_SHA3,
-                      "+sve2,+sve,+sve2-sha3,+fullfp16,+fp-armv8,+neon", 410)
-AARCH64_ARCH_EXT_NAME("sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm",
-                      "-sve2-bitperm", SVE_BITPERM,
-                      "+sve2,+sve,+sve2-bitperm,+fullfp16,+fp-armv8,+neon", 400)
-AARCH64_ARCH_EXT_NAME("sve2p1", AArch64::AEK_SVE2p1, "+sve2p1", "-sve2p1", MAX,
-                      "", 0)
-AARCH64_ARCH_EXT_NAME("b16b16", AArch64::AEK_B16B16, "+b16b16", "-b16b16", MAX,
-                      "", 0)
-AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc", RCPC,
-                      "+rcpc", 230)
-AARCH64_ARCH_EXT_NAME("rcpc2", AArch64::AEK_NONE, {}, {}, RCPC2, "+rcpc", 240)
-AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand", RNG, "+rand",
-                      10)
-AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte", MEMTAG, "",
-                      440)
-AARCH64_ARCH_EXT_NAME("memtag2", AArch64::AEK_NONE, {}, {}, MEMTAG2, "+mte",
-                      450)
-AARCH64_ARCH_EXT_NAME("memtag3", AArch64::AEK_NONE, {}, {}, MEMTAG3, "+mte",
-                      460)
-AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs", SSBS, "",
-                      490)
-AARCH64_ARCH_EXT_NAME("ssbs2", AArch64::AEK_NONE, {}, {}, SSBS2, "+ssbs", 500)
-AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb", SB, "+sb", 470)
-AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres",
-                      PREDRES, "+predres", 480)
-AARCH64_ARCH_EXT_NAME("bf16", AArch64::AEK_BF16, "+bf16", "-bf16", BF16,
-                      "+bf16", 280)
-AARCH64_ARCH_EXT_NAME("i8mm", AArch64::AEK_I8MM, "+i8mm", "-i8mm", I8MM,
-                      "+i8mm", 270)
-AARCH64_ARCH_EXT_NAME("f32mm", AArch64::AEK_F32MM, "+f32mm", "-f32mm",
-                      SVE_F32MM, "+sve,+f32mm,+fullfp16,+fp-armv8,+neon", 350)
-AARCH64_ARCH_EXT_NAME("f64mm", AArch64::AEK_F64MM, "+f64mm", "-f64mm",
-                      SVE_F64MM, "+sve,+f64mm,+fullfp16,+fp-armv8,+neon", 360)
-AARCH64_ARCH_EXT_NAME("tme", AArch64::AEK_TME, "+tme", "-tme", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("ls64", AArch64::AEK_LS64, "+ls64", "-ls64", LS64, "",
-                      520)
-AARCH64_ARCH_EXT_NAME("brbe", AArch64::AEK_BRBE, "+brbe", "-brbe", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("pauth", AArch64::AEK_PAUTH, "+pauth", "-pauth", MAX, "",
-                      0)
-AARCH64_ARCH_EXT_NAME("flagm", AArch64::AEK_FLAGM, "+flagm", "-flagm", FLAGM,
-                      "+flagm", 20)
-AARCH64_ARCH_EXT_NAME("flagm2", AArch64::AEK_NONE, {}, {}, FLAGM2,
-                      "+flagm,+altnzcv", 30)
-AARCH64_ARCH_EXT_NAME("sme", AArch64::AEK_SME, "+sme", "-sme", SME,
-                      "+sme,+bf16", 430)
-AARCH64_ARCH_EXT_NAME("sme-f64f64", AArch64::AEK_SMEF64F64, "+sme-f64f64",
-                      "-sme-f64f64", SME_F64, "+sme,+sme-f64f64,+bf16", 560)
-AARCH64_ARCH_EXT_NAME("sme-i16i64", AArch64::AEK_SMEI16I64, "+sme-i16i64",
-                      "-sme-i16i64", SME_I64, "+sme,+sme-i16i64,+bf16", 570)
-AARCH64_ARCH_EXT_NAME("sme-f16f16", AArch64::AEK_SMEF16F16, "+sme-f16f16",
-                      "-sme-f16f16", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("sme2", AArch64::AEK_SME2, "+sme2", "-sme2", SME2,
-                      "+sme2,+sme,+bf16", 580)
-AARCH64_ARCH_EXT_NAME("sme2p1", AArch64::AEK_SME2p1, "+sme2p1", "-sme2p1", MAX,
-                      "", 0)
-AARCH64_ARCH_EXT_NAME("hbc", AArch64::AEK_HBC, "+hbc", "-hbc", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("mops", AArch64::AEK_MOPS, "+mops", "-mops", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("pmuv3", AArch64::AEK_PERFMON, "+perfmon", "-perfmon",
-                      MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("predres2", AArch64::AEK_SPECRES2, "+specres2",
-                      "-specres2", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("cssc", AArch64::AEK_CSSC, "+cssc", "-cssc", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("rcpc3", AArch64::AEK_RCPC3, "+rcpc3", "-rcpc3", MAX, "",
-                      0)
-AARCH64_ARCH_EXT_NAME("the", AArch64::AEK_THE, "+the", "-the", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("d128", AArch64::AEK_D128, "+d128", "-d128", MAX, "", 0)
-AARCH64_ARCH_EXT_NAME("lse128", AArch64::AEK_LSE128, "+lse128", "-lse128", MAX,
-                      "", 0)
-AARCH64_ARCH_EXT_NAME("sha1", AArch64::AEK_NONE, {}, {}, SHA1,
-                      "+fp-armv8,+neon", 120)
-AARCH64_ARCH_EXT_NAME("pmull", AArch64::AEK_NONE, {}, {}, PMULL,
-                      "+aes,+fp-armv8,+neon", 160)
-AARCH64_ARCH_EXT_NAME("dit", AArch64::AEK_NONE, {}, {}, DIT, "+dit", 180)
-AARCH64_ARCH_EXT_NAME("dpb", AArch64::AEK_NONE, {}, {}, DPB, "+ccpp", 190)
-AARCH64_ARCH_EXT_NAME("dpb2", AArch64::AEK_NONE, {}, {}, DPB2, "+ccpp,+ccdp",
-                      200)
-AARCH64_ARCH_EXT_NAME("jscvt", AArch64::AEK_NONE, {}, {}, JSCVT,
-                      "+fp-armv8,+neon,+jsconv", 210)
-AARCH64_ARCH_EXT_NAME("fcma", AArch64::AEK_NONE, {}, {}, FCMA,
-                      "+fp-armv8,+neon,+complxnum", 220)
-AARCH64_ARCH_EXT_NAME("frintts", AArch64::AEK_NONE, {}, {}, FRINTTS, "+fptoint",
-                      250)
-AARCH64_ARCH_EXT_NAME("dgh", AArch64::AEK_NONE, {}, {}, DGH, "", 260)
-AARCH64_ARCH_EXT_NAME("ebf16", AArch64::AEK_NONE, {}, {}, EBF16, "+bf16", 290)
-AARCH64_ARCH_EXT_NAME("rpres", AArch64::AEK_NONE, {}, {}, RPRES, "", 300)
-AARCH64_ARCH_EXT_NAME("sve-bf16", AArch64::AEK_NONE, {}, {}, SVE_BF16,
-                      "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 320)
-AARCH64_ARCH_EXT_NAME("sve-ebf16", AArch64::AEK_NONE, {}, {}, SVE_EBF16,
-                      "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 330)
-AARCH64_ARCH_EXT_NAME("sve-i8mm", AArch64::AEK_NONE, {}, {}, SVE_I8MM,
-                      "+sve,+i8mm,+fullfp16,+fp-armv8,+neon", 340)
-AARCH64_ARCH_EXT_NAME("sve2-pmull128", AArch64::AEK_NONE, {}, {}, SVE_PMULL128,
-                      "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 390)
-AARCH64_ARCH_EXT_NAME("bti", AArch64::AEK_NONE, {}, {}, BTI, "+bti", 510)
-AARCH64_ARCH_EXT_NAME("ls64_v", AArch64::AEK_NONE, {}, {}, LS64_V, "", 530)
-AARCH64_ARCH_EXT_NAME("ls64_accdata", AArch64::AEK_NONE, {}, {}, LS64_ACCDATA,
-                      "+ls64", 540)
-AARCH64_ARCH_EXT_NAME("wfxt", AArch64::AEK_NONE, {}, {}, WFXT, "+wfxt", 550)
-#undef AARCH64_ARCH_EXT_NAME
-
-#ifndef AARCH64_CPU_NAME
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_EXT)
-#endif
-AARCH64_CPU_NAME("cortex-a34", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a35", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a53", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a55", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC))
-AARCH64_CPU_NAME("cortex-a510", ARMV9A,
-                 (AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SB |
-                  AArch64::AEK_PAUTH | AArch64::AEK_MTE | AArch64::AEK_SSBS |
-                  AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
-                  AArch64::AEK_FP16FML))
-AARCH64_CPU_NAME("cortex-a57", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a65", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
-                  AArch64::AEK_RCPC | AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("cortex-a65ae", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
-                  AArch64::AEK_RCPC | AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("cortex-a72", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a73", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("cortex-a75", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC))
-AARCH64_CPU_NAME("cortex-a76", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("cortex-a76ae", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("cortex-a77", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
-                  AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("cortex-a78", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS | AArch64::AEK_PROFILE))
-AARCH64_CPU_NAME("cortex-a78c", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS | AArch64::AEK_PROFILE | AArch64::AEK_FLAGM |
-                  AArch64::AEK_PAUTH | AArch64::AEK_FP16FML))
-AARCH64_CPU_NAME("cortex-a710", ARMV9A,
-                 (AArch64::AEK_MTE | AArch64::AEK_PAUTH | AArch64::AEK_FLAGM |
-                  AArch64::AEK_SB | AArch64::AEK_I8MM | AArch64::AEK_FP16FML |
-                  AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
-                  AArch64::AEK_BF16))
-AARCH64_CPU_NAME("cortex-a715", ARMV9A,
-                 (AArch64::AEK_SB | AArch64::AEK_SSBS | AArch64::AEK_MTE |
-                  AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PAUTH |
-                  AArch64::AEK_I8MM | AArch64::AEK_PREDRES | AArch64::AEK_PERFMON |
-                  AArch64::AEK_PROFILE | AArch64::AEK_SVE | AArch64::AEK_SVE2BITPERM |
-                  AArch64::AEK_BF16 | AArch64::AEK_FLAGM))
-AARCH64_CPU_NAME("cortex-r82", ARMV8R,
-                 (AArch64::AEK_LSE))
-AARCH64_CPU_NAME("cortex-x1", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS | AArch64::AEK_PROFILE))
-AARCH64_CPU_NAME("cortex-x1c", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS | AArch64::AEK_PAUTH | AArch64::AEK_PROFILE))
-AARCH64_CPU_NAME("cortex-x2", ARMV9A,
-                 (AArch64::AEK_MTE | AArch64::AEK_BF16 | AArch64::AEK_I8MM |
-                  AArch64::AEK_PAUTH | AArch64::AEK_SSBS | AArch64::AEK_SB |
-                  AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
-                  AArch64::AEK_FP16FML))
-AARCH64_CPU_NAME("cortex-x3", ARMV9A,
-                 (AArch64::AEK_SVE | AArch64::AEK_PERFMON | AArch64::AEK_PROFILE |
-                  AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_MTE |
-                  AArch64::AEK_SVE2BITPERM | AArch64::AEK_SB | AArch64::AEK_PAUTH |
-                  AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PREDRES |
-                  AArch64::AEK_FLAGM | AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("neoverse-e1", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
-                  AArch64::AEK_RCPC | AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("neoverse-n1", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
-                  AArch64::AEK_PROFILE | AArch64::AEK_RCPC |
-                  AArch64::AEK_SSBS))
-AARCH64_CPU_NAME("neoverse-n2", ARMV8_5A,
-                 (AArch64::AEK_BF16 | AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
-                  AArch64::AEK_I8MM | AArch64::AEK_MTE |
-                  AArch64::AEK_SB | AArch64::AEK_SSBS |
-                  AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM))
-AARCH64_CPU_NAME("neoverse-512tvb", ARMV8_4A,
-                 (AArch64::AEK_SVE | AArch64::AEK_SSBS |
-                  AArch64::AEK_FP16 | AArch64::AEK_BF16 |
-                  AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE |
-                  AArch64::AEK_RAND | AArch64::AEK_FP16FML | AArch64::AEK_I8MM))
-AARCH64_CPU_NAME("neoverse-v1", ARMV8_4A,
-                 (AArch64::AEK_SVE | AArch64::AEK_SSBS |
-                  AArch64::AEK_FP16 | AArch64::AEK_BF16 |
-                  AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE |
-                  AArch64::AEK_RAND | AArch64::AEK_FP16FML | AArch64::AEK_I8MM))
-AARCH64_CPU_NAME("neoverse-v2", ARMV9A,
-                 (AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SSBS |
-                  AArch64::AEK_FP16 | AArch64::AEK_BF16 | AArch64::AEK_RAND |
-                  AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE |
-                  AArch64::AEK_SVE2BITPERM | AArch64::AEK_FP16FML |
-                  AArch64::AEK_I8MM | AArch64::AEK_MTE))
-AARCH64_CPU_NAME("cyclone", ARMV8A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("apple-a7", ARMV8A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("apple-a8", ARMV8A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("apple-a9", ARMV8A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("apple-a10", ARMV8A,
-                 (AArch64::AEK_CRC | AArch64::AEK_RDM))
-AARCH64_CPU_NAME("apple-a11", ARMV8_2A,
-                 (AArch64::AEK_FP16))
-AARCH64_CPU_NAME("apple-a12", ARMV8_3A,
-                 (AArch64::AEK_FP16))
-AARCH64_CPU_NAME("apple-a13", ARMV8_4A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3))
-AARCH64_CPU_NAME("apple-a14", ARMV8_5A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3))
-AARCH64_CPU_NAME("apple-a15", ARMV8_5A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
-                  AArch64::AEK_BF16 | AArch64::AEK_I8MM))
-AARCH64_CPU_NAME("apple-a16", ARMV8_5A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
-                  AArch64::AEK_BF16 | AArch64::AEK_I8MM))
-AARCH64_CPU_NAME("apple-m1", ARMV8_5A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3))
-AARCH64_CPU_NAME("apple-m2", ARMV8_5A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
-                  AArch64::AEK_BF16 | AArch64::AEK_I8MM))
-AARCH64_CPU_NAME("apple-s4", ARMV8_3A,
-                 (AArch64::AEK_FP16))
-AARCH64_CPU_NAME("apple-s5", ARMV8_3A,
-                 (AArch64::AEK_FP16))
-AARCH64_CPU_NAME("exynos-m3", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("exynos-m4", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16))
-AARCH64_CPU_NAME("exynos-m5", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD | AArch64::AEK_FP16))
-AARCH64_CPU_NAME("falkor", ARMV8A,
-                 (AArch64::AEK_CRC | AArch64::AEK_RDM))
-AARCH64_CPU_NAME("saphira", ARMV8_3A,
-                 (AArch64::AEK_PROFILE))
-AARCH64_CPU_NAME("kryo", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("thunderx2t99", ARMV8_1A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("thunderx3t110", ARMV8_3A,
-                 (AArch64::AEK_NONE))
-AARCH64_CPU_NAME("thunderx", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("thunderxt88", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("thunderxt81", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("thunderxt83", ARMV8A,
-                 (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("tsv110", ARMV8_2A,
-                 (AArch64::AEK_DOTPROD |
-                  AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
-                  AArch64::AEK_PROFILE))
-AARCH64_CPU_NAME("a64fx", ARMV8_2A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_SVE))
-AARCH64_CPU_NAME("carmel", ARMV8_2A,
-                 AArch64::AEK_FP16)
-AARCH64_CPU_NAME("ampere1", ARMV8_6A,
-                 (AArch64::AEK_FP16 | AArch64::AEK_SB | AArch64::AEK_SSBS))
-// Invalid CPU
-AARCH64_CPU_NAME("invalid", INVALID, AArch64::AEK_INVALID)
-#undef AARCH64_CPU_NAME
-
-#ifndef AARCH64_CPU_ALIAS
-#define AARCH64_CPU_ALIAS(ALIAS,NAME)
-#endif
-AARCH64_CPU_ALIAS("grace", "neoverse-v2")
-#undef AARCH64_CPU_ALIAS

diff  --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h
index 309e35568bf5f..0ffec6bb9bf48 100644
--- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h
+++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h
@@ -16,9 +16,10 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include <array>
 #include <vector>
 
-// FIXME:This should be made into class design,to avoid dupplication.
 namespace llvm {
 
 class Triple;
@@ -149,103 +150,356 @@ enum ArchExtKind : uint64_t {
 };
 // clang-format on
 
-enum class ArchKind {
-#define AARCH64_ARCH(NAME, ID, ARCH_FEATURE, ARCH_BASE_EXT) ID,
-#include "AArch64TargetParser.def"
+// Represents an extension that can be enabled with -march=<arch>+<extension>.
+// Typically these correspond to Arm Architecture extensions, unlike
+// SubtargetFeature which may represent either an actual extension or some
+// internal LLVM property.
+struct ExtensionInfo {
+  StringRef Name;       // Human readable name, e.g. "profile".
+  ArchExtKind ID;       // Corresponding to the ArchExtKind, this extensions
+                        // representation in the bitfield.
+  StringRef Feature;    // -mattr enable string, e.g. "+spe"
+  StringRef NegFeature; // -mattr disable string, e.g. "-spe"
+
+  // FIXME These were added by D127812 FMV support and need documenting:
+  CPUFeatures CPUFeature; // Bitfield value set in __aarch64_cpu_features
+  StringRef DependentFeatures;
+  unsigned FmvPriority;
+  static constexpr unsigned MaxFMVPriority = 1000;
 };
 
-struct ArchNames {
-  StringRef Name;
-  StringRef ArchFeature;
-  uint64_t ArchBaseExtensions;
-  ArchKind ID;
+// clang-format off
+inline constexpr ExtensionInfo Extensions[] = {
+    {"aes", AArch64::AEK_AES, "+aes", "-aes", FEAT_AES, "+fp-armv8,+neon", 150},
+    {"b16b16", AArch64::AEK_B16B16, "+b16b16", "-b16b16", FEAT_MAX, "", 0},
+    {"bf16", AArch64::AEK_BF16, "+bf16", "-bf16", FEAT_BF16, "+bf16", 280},
+    {"brbe", AArch64::AEK_BRBE, "+brbe", "-brbe", FEAT_MAX, "", 0},
+    {"bti", AArch64::AEK_NONE, {}, {}, FEAT_BTI, "+bti", 510},
+    {"crc", AArch64::AEK_CRC, "+crc", "-crc", FEAT_CRC, "+crc", 110},
+    {"crypto", AArch64::AEK_CRYPTO, "+crypto", "-crypto", FEAT_MAX, "", 0},
+    {"cssc", AArch64::AEK_CSSC, "+cssc", "-cssc", FEAT_MAX, "", 0},
+    {"d128", AArch64::AEK_D128, "+d128", "-d128", FEAT_MAX, "", 0},
+    {"dgh", AArch64::AEK_NONE, {}, {}, FEAT_DGH, "", 260},
+    {"dit", AArch64::AEK_NONE, {}, {}, FEAT_DIT, "+dit", 180},
+    {"dotprod", AArch64::AEK_DOTPROD, "+dotprod", "-dotprod", FEAT_DOTPROD, "+dotprod,+fp-armv8,+neon", 50},
+    {"dpb", AArch64::AEK_NONE, {}, {}, FEAT_DPB, "+ccpp", 190},
+    {"dpb2", AArch64::AEK_NONE, {}, {}, FEAT_DPB2, "+ccpp,+ccdp", 200},
+    {"ebf16", AArch64::AEK_NONE, {}, {}, FEAT_EBF16, "+bf16", 290},
+    {"f32mm", AArch64::AEK_F32MM, "+f32mm", "-f32mm", FEAT_SVE_F32MM, "+sve,+f32mm,+fullfp16,+fp-armv8,+neon", 350},
+    {"f64mm", AArch64::AEK_F64MM, "+f64mm", "-f64mm", FEAT_SVE_F64MM, "+sve,+f64mm,+fullfp16,+fp-armv8,+neon", 360},
+    {"fcma", AArch64::AEK_NONE, {}, {}, FEAT_FCMA, "+fp-armv8,+neon,+complxnum", 220},
+    {"flagm", AArch64::AEK_FLAGM, "+flagm", "-flagm", FEAT_FLAGM, "+flagm", 20},
+    {"flagm2", AArch64::AEK_NONE, {}, {}, FEAT_FLAGM2, "+flagm,+altnzcv", 30},
+    {"fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8", FEAT_FP, "+fp-armv8,+neon", 90},
+    {"fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16", FEAT_FP16, "+fullfp16,+fp-armv8,+neon", 170},
+    {"fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml", FEAT_FP16FML, "+fp16fml,+fullfp16,+fp-armv8,+neon", 40},
+    {"frintts", AArch64::AEK_NONE, {}, {}, FEAT_FRINTTS, "+fptoint", 250},
+    {"hbc", AArch64::AEK_HBC, "+hbc", "-hbc", FEAT_MAX, "", 0},
+    {"i8mm", AArch64::AEK_I8MM, "+i8mm", "-i8mm", FEAT_I8MM, "+i8mm", 270},
+    {"jscvt", AArch64::AEK_NONE, {}, {}, FEAT_JSCVT, "+fp-armv8,+neon,+jsconv", 210},
+    {"ls64_accdata", AArch64::AEK_NONE, {}, {}, FEAT_LS64_ACCDATA, "+ls64", 540},
+    {"ls64_v", AArch64::AEK_NONE, {}, {}, FEAT_LS64_V, "", 530},
+    {"ls64", AArch64::AEK_LS64, "+ls64", "-ls64", FEAT_LS64, "", 520},
+    {"lse", AArch64::AEK_LSE, "+lse", "-lse", FEAT_LSE, "+lse", 80},
+    {"lse128", AArch64::AEK_LSE128, "+lse128", "-lse128", FEAT_MAX, "", 0},
+    {"memtag", AArch64::AEK_MTE, "+mte", "-mte", FEAT_MEMTAG, "", 440},
+    {"memtag2", AArch64::AEK_NONE, {}, {}, FEAT_MEMTAG2, "+mte", 450},
+    {"memtag3", AArch64::AEK_NONE, {}, {}, FEAT_MEMTAG3, "+mte", 460},
+    {"mops", AArch64::AEK_MOPS, "+mops", "-mops", FEAT_MAX, "", 0},
+    {"pauth", AArch64::AEK_PAUTH, "+pauth", "-pauth", FEAT_MAX, "", 0},
+    {"pmull", AArch64::AEK_NONE, {}, {}, FEAT_PMULL, "+aes,+fp-armv8,+neon", 160},
+    {"pmuv3", AArch64::AEK_PERFMON, "+perfmon", "-perfmon", FEAT_MAX, "", 0},
+    {"predres", AArch64::AEK_PREDRES, "+predres", "-predres", FEAT_PREDRES, "+predres", 480},
+    {"predres2", AArch64::AEK_SPECRES2, "+specres2", "-specres2", FEAT_MAX, "", 0},
+    {"profile", AArch64::AEK_PROFILE, "+spe", "-spe", FEAT_MAX, "", 0},
+    {"ras", AArch64::AEK_RAS, "+ras", "-ras", FEAT_MAX, "", 0},
+    {"rasv2", AArch64::AEK_RASv2, "+rasv2", "-rasv2", FEAT_MAX, "", 0},
+    {"rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc", FEAT_RCPC, "+rcpc", 230},
+    {"rcpc2", AArch64::AEK_NONE, {}, {}, FEAT_RCPC2, "+rcpc", 240},
+    {"rcpc3", AArch64::AEK_RCPC3, "+rcpc3", "-rcpc3", FEAT_MAX, "", 0},
+    {"rdm", AArch64::AEK_RDM, "+rdm", "-rdm", FEAT_RDM, "+rdm,+fp-armv8,+neon", 70},
+    {"rng", AArch64::AEK_RAND, "+rand", "-rand", FEAT_RNG, "+rand", 10},
+    {"rpres", AArch64::AEK_NONE, {}, {}, FEAT_RPRES, "", 300},
+    {"sb", AArch64::AEK_SB, "+sb", "-sb", FEAT_SB, "+sb", 470},
+    {"sha1", AArch64::AEK_NONE, {}, {}, FEAT_SHA1, "+fp-armv8,+neon", 120},
+    {"sha2", AArch64::AEK_SHA2, "+sha2", "-sha2", FEAT_SHA2, "+sha2,+fp-armv8,+neon", 130},
+    {"sha3", AArch64::AEK_SHA3, "+sha3", "-sha3", FEAT_SHA3, "+sha3,+sha2,+fp-armv8,+neon", 140},
+    {"simd", AArch64::AEK_SIMD, "+neon", "-neon", FEAT_SIMD, "+fp-armv8,+neon", 100},
+    {"sm4", AArch64::AEK_SM4, "+sm4", "-sm4", FEAT_SM4, "+sm4,+fp-armv8,+neon", 60},
+    {"sme-f16f16", AArch64::AEK_SMEF16F16, "+sme-f16f16", "-sme-f16f16", FEAT_MAX, "", 0},
+    {"sme-f64f64", AArch64::AEK_SMEF64F64, "+sme-f64f64", "-sme-f64f64", FEAT_SME_F64, "+sme,+sme-f64f64,+bf16", 560},
+    {"sme-i16i64", AArch64::AEK_SMEI16I64, "+sme-i16i64", "-sme-i16i64", FEAT_SME_I64, "+sme,+sme-i16i64,+bf16", 570},
+    {"sme", AArch64::AEK_SME, "+sme", "-sme", FEAT_SME, "+sme,+bf16", 430},
+    {"sme2", AArch64::AEK_SME2, "+sme2", "-sme2", FEAT_SME2, "+sme2,+sme,+bf16", 580},
+    {"sme2p1", AArch64::AEK_SME2p1, "+sme2p1", "-sme2p1", FEAT_MAX, "", 0},
+    {"ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs", FEAT_SSBS, "", 490},
+    {"ssbs2", AArch64::AEK_NONE, {}, {}, FEAT_SSBS2, "+ssbs", 500},
+    {"sve-bf16", AArch64::AEK_NONE, {}, {}, FEAT_SVE_BF16, "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 320},
+    {"sve-ebf16", AArch64::AEK_NONE, {}, {}, FEAT_SVE_EBF16, "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 330},
+    {"sve-i8mm", AArch64::AEK_NONE, {}, {}, FEAT_SVE_I8MM, "+sve,+i8mm,+fullfp16,+fp-armv8,+neon", 340},
+    {"sve", AArch64::AEK_SVE, "+sve", "-sve", FEAT_SVE, "+sve,+fullfp16,+fp-armv8,+neon", 310},
+    {"sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes", FEAT_SVE_AES, "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 380},
+    {"sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm", FEAT_SVE_BITPERM, "+sve2,+sve,+sve2-bitperm,+fullfp16,+fp-armv8,+neon", 400},
+    {"sve2-pmull128", AArch64::AEK_NONE, {}, {}, FEAT_SVE_PMULL128, "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 390},
+    {"sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3", FEAT_SVE_SHA3, "+sve2,+sve,+sve2-sha3,+fullfp16,+fp-armv8,+neon", 410},
+    {"sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4", FEAT_SVE_SM4, "+sve2,+sve,+sve2-sm4,+fullfp16,+fp-armv8,+neon", 420},
+    {"sve2", AArch64::AEK_SVE2, "+sve2", "-sve2", FEAT_SVE2, "+sve2,+sve,+fullfp16,+fp-armv8,+neon", 370},
+    {"sve2p1", AArch64::AEK_SVE2p1, "+sve2p1", "-sve2p1", FEAT_MAX, "", 0},
+    {"the", AArch64::AEK_THE, "+the", "-the", FEAT_MAX, "", 0},
+    {"tme", AArch64::AEK_TME, "+tme", "-tme", FEAT_MAX, "", 0},
+    {"wfxt", AArch64::AEK_NONE, {}, {}, FEAT_WFXT, "+wfxt", 550},
+    // Special cases
+    {"none", AArch64::AEK_NONE, {}, {}, FEAT_MAX, "", ExtensionInfo::MaxFMVPriority},
+    {"invalid", AArch64::AEK_INVALID, {}, {}, FEAT_MAX, "", 0},
+};
+// clang-format on
+
+enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
+
+// Information about a specific architecture, e.g. V8.1-A
+struct ArchInfo {
+  VersionTuple Version;  // Architecture version, major + minor.
+  ArchProfile Profile;   // Architecuture profile
+  StringRef Name;        // Human readable name, e.g. "armv8.1-a"
+  StringRef ArchFeature; // Command line feature flag, e.g. +v8a
+  uint64_t DefaultExts;  // bitfield of default extensions ArchExtKind
+
+  bool operator==(const ArchInfo &Other) const {
+    return this->Name == Other.Name;
+  }
+  bool operator!=(const ArchInfo &Other) const {
+    return this->Name != Other.Name;
+  }
+
+  // Defines the following partial order, indicating when an architecture is
+  // a superset of another:
+  //
+  //     v9.4a > v9.3a > v9.3a > v9.3a > v9a;
+  //       v       v       v       v       v
+  //     v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
+  //
+  // v8r and INVALID have no relation to anything. This is used to
+  // determine which features to enable for a given architecture. See
+  // AArch64TargetInfo::setFeatureEnabled.
+  bool implies(const ArchInfo &Other) const {
+    if (this->Profile != Other.Profile)
+      return false; // ARMV8R and INVALID
+    if (this->Version.getMajor() == Other.Version.getMajor()) {
+      return this->Version > Other.Version;
+    }
+    if (this->Version.getMajor() == 9 && Other.Version.getMajor() == 8) {
+      return this->Version.getMinor().value() + 5 >=
+             Other.Version.getMinor().value();
+    }
+    return false;
+  }
 
   // Return ArchFeature without the leading "+".
   StringRef getSubArch() const { return ArchFeature.substr(1); }
-};
 
-const ArchNames AArch64ARCHNames[] = {
-#define AARCH64_ARCH(NAME, ID, ARCH_FEATURE, ARCH_BASE_EXT)                    \
-  {NAME, ARCH_FEATURE, ARCH_BASE_EXT, AArch64::ArchKind::ID},
-#include "AArch64TargetParser.def"
+  // Search for ArchInfo by SubArch name
+  static const ArchInfo &findBySubArch(StringRef SubArch);
 };
 
-// List of Arch Extension names.
-struct ExtName {
-  StringRef Name;
-  uint64_t ID;
-  StringRef Feature;
-  StringRef NegFeature;
-};
+// clang-format off
+inline constexpr ArchInfo INVALID   = { VersionTuple{0, 0}, AProfile, "invalid", "+", (AArch64::AEK_NONE)};
+inline constexpr ArchInfo ARMV8A    = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", (AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD), };
+inline constexpr ArchInfo ARMV8_1A  = { VersionTuple{8, 1}, AProfile, "armv8.1-a", "+v8.1a", (ARMV8A.DefaultExts | AArch64::AEK_CRC | AArch64::AEK_LSE | AArch64::AEK_RDM)};
+inline constexpr ArchInfo ARMV8_2A  = { VersionTuple{8, 2}, AProfile, "armv8.2-a", "+v8.2a", (ARMV8_1A.DefaultExts | AArch64::AEK_RAS)};
+inline constexpr ArchInfo ARMV8_3A  = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts | AArch64::AEK_RCPC)};
+inline constexpr ArchInfo ARMV8_4A  = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts | AArch64::AEK_DOTPROD)};
+inline constexpr ArchInfo ARMV8_5A  = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)};
+constexpr unsigned BaseNoCrypto = ARMV8_5A.DefaultExts ^ AArch64::AEK_CRYPTO; // 8.6 onwards has no AEK_CRYPTO
+inline constexpr ArchInfo ARMV8_6A  = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (BaseNoCrypto | AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 | AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM)};
+inline constexpr ArchInfo ARMV8_7A  = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)};
+inline constexpr ArchInfo ARMV8_8A  = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts)};
+inline constexpr ArchInfo ARMV8_9A  = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts)};
+inline constexpr ArchInfo ARMV9A    = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (BaseNoCrypto | AArch64::AEK_SVE | AArch64::AEK_SVE2)};
+inline constexpr ArchInfo ARMV9_1A  = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts | AArch64::AEK_BF16 | AArch64::AEK_I8MM)};
+inline constexpr ArchInfo ARMV9_2A  = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)};
+inline constexpr ArchInfo ARMV9_3A  = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts)};
+inline constexpr ArchInfo ARMV9_4A  = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts)};
+// For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions.
+inline constexpr ArchInfo ARMV8R    = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", ((BaseNoCrypto ^ AArch64::AEK_LSE) | AArch64::AEK_SSBS | AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SB), };
+// clang-format on
 
-const ExtName AArch64ARCHExtNames[] = {
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  {NAME, ID, FEATURE, NEGFEATURE},
-#include "AArch64TargetParser.def"
+// The set of all architectures
+static constexpr std::array<const ArchInfo *, 17> ArchInfos = {
+    &INVALID,  &ARMV8A,   &ARMV8_1A, &ARMV8_2A, &ARMV8_3A, &ARMV8_4A,
+    &ARMV8_5A, &ARMV8_6A, &ARMV8_7A, &ARMV8_8A, &ARMV8_9A, &ARMV9A,
+    &ARMV9_1A, &ARMV9_2A, &ARMV9_3A, &ARMV9_4A, &ARMV8R,
 };
 
-// List of CPU names and their arches.
-// The same CPU can have multiple arches and can be default on multiple arches.
-// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
-// When this becomes table-generated, we'd probably need two tables.
-struct CpuNames {
-  StringRef Name;
-  ArchKind ArchID;
-  uint64_t DefaultExtensions;
+// Details of a specific CPU.
+struct CpuInfo {
+  StringRef Name; // Name, as written for -mcpu.
+  const ArchInfo &Arch;
+  uint64_t DefaultExtensions; // Default extensions for this CPU. These will be
+                              // ORd with the architecture defaults.
 };
 
-const CpuNames AArch64CPUNames[] = {
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_EXT)                                \
-  {NAME, AArch64::ArchKind::ID, DEFAULT_EXT},
-#include "AArch64TargetParser.def"
+inline constexpr CpuInfo CpuInfos[] = {
+    {"cortex-a34", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a35", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a53", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a55", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)},
+    {"cortex-a510", ARMV9A,
+     (AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SB |
+      AArch64::AEK_PAUTH | AArch64::AEK_MTE | AArch64::AEK_SSBS |
+      AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
+      AArch64::AEK_FP16FML)},
+    {"cortex-a57", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a65", ARMV8_2A,
+     (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS)},
+    {"cortex-a65ae", ARMV8_2A,
+     (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS)},
+    {"cortex-a72", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a73", ARMV8A, (AArch64::AEK_CRC)},
+    {"cortex-a75", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)},
+    {"cortex-a76", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS)},
+    {"cortex-a76ae", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS)},
+    {"cortex-a77", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+      AArch64::AEK_SSBS)},
+    {"cortex-a78", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS | AArch64::AEK_PROFILE)},
+    {"cortex-a78c", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS | AArch64::AEK_PROFILE | AArch64::AEK_FLAGM |
+      AArch64::AEK_PAUTH | AArch64::AEK_FP16FML)},
+    {"cortex-a710", ARMV9A,
+     (AArch64::AEK_MTE | AArch64::AEK_PAUTH | AArch64::AEK_FLAGM |
+      AArch64::AEK_SB | AArch64::AEK_I8MM | AArch64::AEK_FP16FML |
+      AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
+      AArch64::AEK_BF16)},
+    {"cortex-a715", ARMV9A,
+     (AArch64::AEK_SB | AArch64::AEK_SSBS | AArch64::AEK_MTE |
+      AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PAUTH |
+      AArch64::AEK_I8MM | AArch64::AEK_PREDRES | AArch64::AEK_PERFMON |
+      AArch64::AEK_PROFILE | AArch64::AEK_SVE | AArch64::AEK_SVE2BITPERM |
+      AArch64::AEK_BF16 | AArch64::AEK_FLAGM)},
+    {"cortex-r82", ARMV8R, (AArch64::AEK_LSE)},
+    {"cortex-x1", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS | AArch64::AEK_PROFILE)},
+    {"cortex-x1c", ARMV8_2A,
+     (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS | AArch64::AEK_PAUTH | AArch64::AEK_PROFILE)},
+    {"cortex-x2", ARMV9A,
+     (AArch64::AEK_MTE | AArch64::AEK_BF16 | AArch64::AEK_I8MM |
+      AArch64::AEK_PAUTH | AArch64::AEK_SSBS | AArch64::AEK_SB |
+      AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
+      AArch64::AEK_FP16FML)},
+    {"cortex-x3", ARMV9A,
+     (AArch64::AEK_SVE | AArch64::AEK_PERFMON | AArch64::AEK_PROFILE |
+      AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_MTE |
+      AArch64::AEK_SVE2BITPERM | AArch64::AEK_SB | AArch64::AEK_PAUTH |
+      AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PREDRES |
+      AArch64::AEK_FLAGM | AArch64::AEK_SSBS)},
+    {"neoverse-e1", ARMV8_2A,
+     (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RCPC |
+      AArch64::AEK_SSBS)},
+    {"neoverse-n1", ARMV8_2A,
+     (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE |
+      AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
+    {"neoverse-n2", ARMV8_5A,
+     (AArch64::AEK_BF16 | AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
+      AArch64::AEK_I8MM | AArch64::AEK_MTE | AArch64::AEK_SB |
+      AArch64::AEK_SSBS | AArch64::AEK_SVE | AArch64::AEK_SVE2 |
+      AArch64::AEK_SVE2BITPERM)},
+    {"neoverse-512tvb", ARMV8_4A,
+     (AArch64::AEK_SVE | AArch64::AEK_SSBS | AArch64::AEK_FP16 |
+      AArch64::AEK_BF16 | AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE |
+      AArch64::AEK_RAND | AArch64::AEK_FP16FML | AArch64::AEK_I8MM)},
+    {"neoverse-v1", ARMV8_4A,
+     (AArch64::AEK_SVE | AArch64::AEK_SSBS | AArch64::AEK_FP16 |
+      AArch64::AEK_BF16 | AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE |
+      AArch64::AEK_RAND | AArch64::AEK_FP16FML | AArch64::AEK_I8MM)},
+    {"neoverse-v2", ARMV9A,
+     (AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SSBS |
+      AArch64::AEK_FP16 | AArch64::AEK_BF16 | AArch64::AEK_RAND |
+      AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE | AArch64::AEK_SVE2BITPERM |
+      AArch64::AEK_FP16FML | AArch64::AEK_I8MM | AArch64::AEK_MTE)},
+    {"cyclone", ARMV8A, (AArch64::AEK_NONE)},
+    {"apple-a7", ARMV8A, (AArch64::AEK_NONE)},
+    {"apple-a8", ARMV8A, (AArch64::AEK_NONE)},
+    {"apple-a9", ARMV8A, (AArch64::AEK_NONE)},
+    {"apple-a10", ARMV8A, (AArch64::AEK_CRC | AArch64::AEK_RDM)},
+    {"apple-a11", ARMV8_2A, (AArch64::AEK_FP16)},
+    {"apple-a12", ARMV8_3A, (AArch64::AEK_FP16)},
+    {"apple-a13", ARMV8_4A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
+    {"apple-a14", ARMV8_5A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
+    {"apple-a15", ARMV8_5A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
+      AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
+    {"apple-a16", ARMV8_5A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
+      AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
+    {"apple-m1", ARMV8_5A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
+    {"apple-m2", ARMV8_5A,
+     (AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
+      AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
+    {"apple-s4", ARMV8_3A, (AArch64::AEK_FP16)},
+    {"apple-s5", ARMV8_3A, (AArch64::AEK_FP16)},
+    {"exynos-m3", ARMV8A, (AArch64::AEK_CRC)},
+    {"exynos-m4", ARMV8_2A, (AArch64::AEK_DOTPROD | AArch64::AEK_FP16)},
+    {"exynos-m5", ARMV8_2A, (AArch64::AEK_DOTPROD | AArch64::AEK_FP16)},
+    {"falkor", ARMV8A, (AArch64::AEK_CRC | AArch64::AEK_RDM)},
+    {"saphira", ARMV8_3A, (AArch64::AEK_PROFILE)},
+    {"kryo", ARMV8A, (AArch64::AEK_CRC)},
+    {"thunderx2t99", ARMV8_1A, (AArch64::AEK_NONE)},
+    {"thunderx3t110", ARMV8_3A, (AArch64::AEK_NONE)},
+    {"thunderx", ARMV8A, (AArch64::AEK_CRC)},
+    {"thunderxt88", ARMV8A, (AArch64::AEK_CRC)},
+    {"thunderxt81", ARMV8A, (AArch64::AEK_CRC)},
+    {"thunderxt83", ARMV8A, (AArch64::AEK_CRC)},
+    {"tsv110", ARMV8_2A,
+     (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
+      AArch64::AEK_PROFILE)},
+    {"a64fx", ARMV8_2A, (AArch64::AEK_FP16 | AArch64::AEK_SVE)},
+    {"carmel", ARMV8_2A, (AArch64::AEK_FP16)},
+    {"ampere1", ARMV8_6A,
+     (AArch64::AEK_FP16 | AArch64::AEK_SB | AArch64::AEK_SSBS)},
+    // Invalid CPU
+    {"invalid", INVALID, (AArch64::AEK_INVALID)},
 };
 
-const struct {
+// An alias for a CPU.
+struct CpuAlias {
   StringRef Alias;
   StringRef Name;
-} AArch64CPUAliases[] = {
-#define AARCH64_CPU_ALIAS(ALIAS, NAME) {ALIAS, NAME},
-#include "AArch64TargetParser.def"
 };
 
-const ArchKind ArchKinds[] = {
-#define AARCH64_ARCH(NAME, ID, ARCH_FEATURE, ARCH_BASE_EXT) ArchKind::ID,
-#include "AArch64TargetParser.def"
-};
-
-inline ArchKind &operator--(ArchKind &Kind) {
-  if ((Kind == ArchKind::INVALID) || (Kind == ArchKind::ARMV8A) ||
-      (Kind == ArchKind::ARMV9A) || (Kind == ArchKind::ARMV8R))
-    Kind = ArchKind::INVALID;
-  else {
-    unsigned KindAsInteger = static_cast<unsigned>(Kind);
-    Kind = static_cast<ArchKind>(--KindAsInteger);
-  }
-  return Kind;
-}
+inline constexpr CpuAlias CpuAliases[] = {{"grace", "neoverse-v2"}};
 
 bool getExtensionFeatures(uint64_t Extensions,
                           std::vector<StringRef> &Features);
-StringRef getArchFeature(ArchKind AK);
 
-StringRef getArchName(ArchKind AK);
-StringRef getSubArch(ArchKind AK);
-StringRef getArchExtName(unsigned ArchExtKind);
 StringRef getArchExtFeature(StringRef ArchExt);
-ArchKind convertV9toV8(ArchKind AK);
 StringRef resolveCPUAlias(StringRef CPU);
 
 // Information by Name
-uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
+uint64_t getDefaultExtensions(StringRef CPU, const ArchInfo &AI);
 void getFeatureOption(StringRef Name, std::string &Feature);
-ArchKind getCPUArchKind(StringRef CPU);
-ArchKind getSubArchArchKind(StringRef SubArch);
+const ArchInfo &getArchForCpu(StringRef CPU);
 
 // Parser
-ArchKind parseArch(StringRef Arch);
+const ArchInfo &parseArch(StringRef Arch);
 ArchExtKind parseArchExt(StringRef ArchExt);
-ArchKind parseCPUArch(StringRef CPU);
+// Given the name of a CPU or alias, return the correponding CpuInfo.
+const CpuInfo &parseCpu(StringRef Name);
 // Used by target parser tests
 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
 
@@ -255,4 +509,4 @@ uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
 } // namespace AArch64
 } // namespace llvm
 
-#endif
+#endif
\ No newline at end of file

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 7d52185ba0754..1ef3ada8764ca 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -6822,67 +6822,48 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
   return false;
 }
 
-static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
+static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
                             SmallVector<StringRef, 4> &RequestedExtensions) {
   const bool NoCrypto = llvm::is_contained(RequestedExtensions, "nocrypto");
   const bool Crypto = llvm::is_contained(RequestedExtensions, "crypto");
 
   if (!NoCrypto && Crypto) {
-    switch (ArchKind) {
-    default:
-      // Map 'generic' (and others) to sha2 and aes, because
-      // that was the traditional meaning of crypto.
-    case AArch64::ArchKind::ARMV8_1A:
-    case AArch64::ArchKind::ARMV8_2A:
-    case AArch64::ArchKind::ARMV8_3A:
+    // Map 'generic' (and others) to sha2 and aes, because
+    // that was the traditional meaning of crypto.
+    if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
+        ArchInfo == AArch64::ARMV8_3A) {
       RequestedExtensions.push_back("sha2");
       RequestedExtensions.push_back("aes");
-      break;
-    case AArch64::ArchKind::ARMV8_4A:
-    case AArch64::ArchKind::ARMV8_5A:
-    case AArch64::ArchKind::ARMV8_6A:
-    case AArch64::ArchKind::ARMV8_7A:
-    case AArch64::ArchKind::ARMV8_8A:
-    case AArch64::ArchKind::ARMV8_9A:
-    case AArch64::ArchKind::ARMV9A:
-    case AArch64::ArchKind::ARMV9_1A:
-    case AArch64::ArchKind::ARMV9_2A:
-    case AArch64::ArchKind::ARMV9_3A:
-    case AArch64::ArchKind::ARMV9_4A:
-    case AArch64::ArchKind::ARMV8R:
+    }
+    if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
+        ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
+        ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
+        ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
+        ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
+        ArchInfo == AArch64::ARMV9_4A || ArchInfo == AArch64::ARMV8R) {
       RequestedExtensions.push_back("sm4");
       RequestedExtensions.push_back("sha3");
       RequestedExtensions.push_back("sha2");
       RequestedExtensions.push_back("aes");
-      break;
     }
   } else if (NoCrypto) {
-    switch (ArchKind) {
-    default:
-      // Map 'generic' (and others) to sha2 and aes, because
-      // that was the traditional meaning of crypto.
-    case AArch64::ArchKind::ARMV8_1A:
-    case AArch64::ArchKind::ARMV8_2A:
-    case AArch64::ArchKind::ARMV8_3A:
+    // Map 'generic' (and others) to sha2 and aes, because
+    // that was the traditional meaning of crypto.
+    if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
+        ArchInfo == AArch64::ARMV8_3A) {
       RequestedExtensions.push_back("nosha2");
       RequestedExtensions.push_back("noaes");
-      break;
-    case AArch64::ArchKind::ARMV8_4A:
-    case AArch64::ArchKind::ARMV8_5A:
-    case AArch64::ArchKind::ARMV8_6A:
-    case AArch64::ArchKind::ARMV8_7A:
-    case AArch64::ArchKind::ARMV8_8A:
-    case AArch64::ArchKind::ARMV8_9A:
-    case AArch64::ArchKind::ARMV9A:
-    case AArch64::ArchKind::ARMV9_1A:
-    case AArch64::ArchKind::ARMV9_2A:
-    case AArch64::ArchKind::ARMV9_3A:
-    case AArch64::ArchKind::ARMV9_4A:
+    }
+    if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
+        ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
+        ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
+        ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
+        ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
+        ArchInfo == AArch64::ARMV9_4A) {
       RequestedExtensions.push_back("nosm4");
       RequestedExtensions.push_back("nosha3");
       RequestedExtensions.push_back("nosha2");
       RequestedExtensions.push_back("noaes");
-      break;
     }
   }
 }
@@ -6896,8 +6877,8 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
   std::tie(Arch, ExtensionString) =
       getParser().parseStringToEndOfStatement().trim().split('+');
 
-  AArch64::ArchKind ID = AArch64::parseArch(Arch);
-  if (ID == AArch64::ArchKind::INVALID)
+  const AArch64::ArchInfo &ArchInfo = AArch64::parseArch(Arch);
+  if (ArchInfo == AArch64::INVALID)
     return Error(ArchLoc, "unknown arch name");
 
   if (parseToken(AsmToken::EndOfStatement))
@@ -6905,9 +6886,9 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
 
   // Get the architecture and extension features.
   std::vector<StringRef> AArch64Features;
-  AArch64Features.push_back(AArch64::getArchFeature(ID));
-  AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
-                                AArch64Features);
+  AArch64Features.push_back(ArchInfo.ArchFeature);
+  AArch64::getExtensionFeatures(
+      AArch64::getDefaultExtensions("generic", ArchInfo), AArch64Features);
 
   MCSubtargetInfo &STI = copySTI();
   std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
@@ -6918,7 +6899,7 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
   if (!ExtensionString.empty())
     ExtensionString.split(RequestedExtensions, '+');
 
-  ExpandCryptoAEK(ID, RequestedExtensions);
+  ExpandCryptoAEK(ArchInfo, RequestedExtensions);
 
   FeatureBitset Features = STI.getFeatureBits();
   for (auto Name : RequestedExtensions) {
@@ -7014,7 +6995,7 @@ bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
   STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
   CurLoc = incrementLoc(CurLoc, CPU.size());
 
-  ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
+  ExpandCryptoAEK(llvm::AArch64::getArchForCpu(CPU), RequestedExtensions);
 
   for (auto Name : RequestedExtensions) {
     // Advance source location past '+'.

diff  --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp
index baa6cbfcdbee6..41d5c2544f292 100644
--- a/llvm/lib/TargetParser/AArch64TargetParser.cpp
+++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp
@@ -25,131 +25,95 @@ static unsigned checkArchVersion(llvm::StringRef Arch) {
   return 0;
 }
 
-uint64_t AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) {
+uint64_t AArch64::getDefaultExtensions(StringRef CPU,
+                                       const AArch64::ArchInfo &AI) {
   if (CPU == "generic")
-    return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
-
-  return StringSwitch<uint64_t>(CPU)
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_EXT)                                \
-  .Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)]            \
-                      .ArchBaseExtensions |                                    \
-                  DEFAULT_EXT)
-#include "../../include/llvm/TargetParser/AArch64TargetParser.def"
-      .Default(AArch64::AEK_INVALID);
+    return AI.DefaultExts;
+
+  // Note: this now takes cpu aliases into account
+  const CpuInfo &Cpu = parseCpu(CPU);
+  return Cpu.Arch.DefaultExts | Cpu.DefaultExtensions;
 }
 
 void AArch64::getFeatureOption(StringRef Name, std::string &Feature) {
-  Feature = llvm::StringSwitch<std::string>(Name.substr(1))
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  .Case(NAME, FEATURE)
-#include "../../include/llvm/TargetParser/AArch64TargetParser.def"
-                .Default(Name.str());
+  for (const auto &E : llvm::AArch64::Extensions) {
+    if (Name == E.Name) {
+      Feature = E.Feature;
+      return;
+    }
+  }
+  Feature = Name.str();
 }
 
-AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
+const AArch64::ArchInfo &AArch64::getArchForCpu(StringRef CPU) {
   if (CPU == "generic")
-    return ArchKind::ARMV8A;
+    return ARMV8A;
 
-  return StringSwitch<AArch64::ArchKind>(CPU)
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_EXT) .Case(NAME, ArchKind::ID)
-#include "../../include/llvm/TargetParser/AArch64TargetParser.def"
-      .Default(ArchKind::INVALID);
+  // Note: this now takes cpu aliases into account
+  const CpuInfo &Cpu = parseCpu(CPU);
+  return Cpu.Arch;
 }
 
-AArch64::ArchKind AArch64::getSubArchArchKind(StringRef SubArch) {
-  for (const auto &A : AArch64ARCHNames)
-    if (A.getSubArch() == SubArch)
-      return A.ID;
-  return ArchKind::INVALID;
+const AArch64::ArchInfo &AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
+  for (const auto *A : AArch64::ArchInfos)
+    if (A->getSubArch() == SubArch)
+      return *A;
+  return AArch64::INVALID;
 }
 
 uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
   uint64_t FeaturesMask = 0;
   for (const StringRef &FeatureStr : FeatureStrs) {
-    unsigned Feature = StringSwitch<unsigned>(FeatureStr)
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  .Case(NAME, llvm::AArch64::FEAT_##FMV_ID)
-#include "../../include/llvm/TargetParser/AArch64TargetParser.def"
-        ;
-    FeaturesMask |= (1ULL << Feature);
+    for (const auto &E : llvm::AArch64::Extensions)
+      if (FeatureStr == E.Name) {
+        FeaturesMask |= (1ULL << E.CPUFeature);
+        break;
+      }
   }
   return FeaturesMask;
 }
 
-bool AArch64::getExtensionFeatures(uint64_t Extensions,
+bool AArch64::getExtensionFeatures(uint64_t InputExts,
                                    std::vector<StringRef> &Features) {
-  if (Extensions == AArch64::AEK_INVALID)
+  if (InputExts == AArch64::AEK_INVALID)
     return false;
 
-#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE, FMV_ID,           \
-                              DEP_FEATURES, FMV_PRIORITY)                      \
-  if (Extensions & ID) {                                                       \
-    const char *feature = FEATURE;                                             \
-    /* INVALID and NONE have no feature name. */                               \
-    if (feature)                                                               \
-      Features.push_back(feature);                                             \
-  }
-#include "llvm/TargetParser/AArch64TargetParser.def"
+  for (const auto &E : Extensions)
+    /* INVALID and NONE have no feature name. */
+    if ((InputExts & E.ID) && !E.Feature.empty())
+      Features.push_back(E.Feature);
 
   return true;
 }
 
-StringRef AArch64::resolveCPUAlias(StringRef CPU) {
-  return StringSwitch<StringRef>(CPU)
-#define AARCH64_CPU_ALIAS(ALIAS, NAME) .Case(ALIAS, NAME)
-#include "../../include/llvm/TargetParser/AArch64TargetParser.def"
-      .Default(CPU);
-}
-
-StringRef AArch64::getArchFeature(AArch64::ArchKind AK) {
-  return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchFeature;
-}
-
-StringRef AArch64::getArchName(AArch64::ArchKind AK) {
-  return AArch64ARCHNames[static_cast<unsigned>(AK)].Name;
-}
-
-StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
-  return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
+StringRef AArch64::resolveCPUAlias(StringRef Name) {
+  for (const auto &A : CpuAliases)
+    if (A.Alias == Name)
+      return A.Name;
+  return Name;
 }
 
 StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
   if (ArchExt.startswith("no")) {
     StringRef ArchExtBase(ArchExt.substr(2));
-    for (const auto &AE : AArch64ARCHExtNames) {
+    for (const auto &AE : Extensions) {
       if (!AE.NegFeature.empty() && ArchExtBase == AE.Name)
         return AE.NegFeature;
     }
   }
 
-  for (const auto &AE : AArch64ARCHExtNames)
+  for (const auto &AE : Extensions)
     if (!AE.Feature.empty() && ArchExt == AE.Name)
       return AE.Feature;
   return StringRef();
 }
 
-AArch64::ArchKind AArch64::convertV9toV8(AArch64::ArchKind AK) {
-  if (AK == AArch64::ArchKind::INVALID)
-    return AK;
-  if (AK < AArch64::ArchKind::ARMV9A)
-    return AK;
-  if (AK >= AArch64::ArchKind::ARMV8R)
-    return AArch64::ArchKind::INVALID;
-  unsigned AK_v8 = static_cast<unsigned>(AArch64::ArchKind::ARMV8_5A);
-  AK_v8 += static_cast<unsigned>(AK) -
-           static_cast<unsigned>(AArch64::ArchKind::ARMV9A);
-  return static_cast<AArch64::ArchKind>(AK_v8);
-}
-
 void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
-  for (const auto &Arch : AArch64CPUNames) {
-    if (Arch.ArchID != ArchKind::INVALID)
-      Values.push_back(Arch.Name);
-  }
+  for (const auto &C : CpuInfos)
+    if (C.Arch != INVALID)
+      Values.push_back(C.Name);
 
-  for (const auto &Alias: AArch64CPUAliases)
+  for (const auto &Alias : CpuAliases)
     Values.push_back(Alias.Alias);
 }
 
@@ -159,39 +123,37 @@ bool AArch64::isX18ReservedByDefault(const Triple &TT) {
 }
 
 // Allows partial match, ex. "v8a" matches "armv8a".
-AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
+const AArch64::ArchInfo &AArch64::parseArch(StringRef Arch) {
   Arch = llvm::ARM::getCanonicalArchName(Arch);
   if (checkArchVersion(Arch) < 8)
-    return ArchKind::INVALID;
+    return AArch64::INVALID;
 
   StringRef Syn = llvm::ARM::getArchSynonym(Arch);
-  for (const auto &A : AArch64ARCHNames) {
-    if (A.Name.endswith(Syn))
-      return A.ID;
+  for (const auto *A : ArchInfos) {
+    if (A->Name.endswith(Syn))
+      return *A;
   }
-  return ArchKind::INVALID;
+  return AArch64::INVALID;
 }
 
 AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
-  for (const auto &A : AArch64ARCHExtNames) {
+  for (const auto &A : Extensions) {
     if (ArchExt == A.Name)
       return static_cast<ArchExtKind>(A.ID);
   }
   return AArch64::AEK_INVALID;
 }
 
-AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
+const AArch64::CpuInfo &AArch64::parseCpu(StringRef Name) {
   // Resolve aliases first.
-  for (const auto &Alias : AArch64CPUAliases) {
-    if (CPU == Alias.Alias) {
-      CPU = Alias.Name;
-      break;
-    }
-  }
+  Name = resolveCPUAlias(Name);
+
   // Then find the CPU name.
-  for (const auto &C : AArch64CPUNames)
-    if (CPU == C.Name)
-      return C.ArchID;
+  for (const auto &C : CpuInfos)
+    if (Name == C.Name)
+      return C;
 
-  return ArchKind::INVALID;
+  // "generic" returns invalid.
+  assert(Name != "invalid" && "Unexpected recursion.");
+  return parseCpu("invalid");
 }

diff  --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index 69e6a73d94533..7bf20ef87436b 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -953,11 +953,11 @@ class AArch64CPUTestFixture
 TEST_P(AArch64CPUTestFixture, testAArch64CPU) {
   ARMCPUTestParams params = GetParam();
 
-  AArch64::ArchKind AK = AArch64::parseCPUArch(params.CPUName);
-  EXPECT_EQ(params.ExpectedArch, AArch64::getArchName(AK));
+  const AArch64::ArchInfo &AI = AArch64::parseCpu(params.CPUName).Arch;
+  EXPECT_EQ(params.ExpectedArch, AI.Name);
 
   uint64_t default_extensions =
-      AArch64::getDefaultExtensions(params.CPUName, AK);
+      AArch64::getDefaultExtensions(params.CPUName, AI);
   EXPECT_PRED_FORMAT2(AssertSameExtensionFlags<ARM::ISAKind::AARCH64>,
                       params.ExpectedFlags, default_extensions);
 }
@@ -1403,14 +1403,14 @@ TEST(TargetParserTest, testAArch64CPUArchList) {
   // valid, and match the expected 'magic' count.
   EXPECT_EQ(List.size(), NumAArch64CPUArchs);
   for(StringRef CPU : List) {
-    EXPECT_NE(AArch64::parseCPUArch(CPU), AArch64::ArchKind::INVALID);
+    EXPECT_NE(AArch64::parseCpu(CPU).Arch, AArch64::INVALID);
   }
 }
 
 bool testAArch64Arch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,
                      unsigned ArchAttr) {
-  AArch64::ArchKind AK = AArch64::parseArch(Arch);
-  return AK != AArch64::ArchKind::INVALID;
+  const AArch64::ArchInfo &AI = AArch64::parseArch(Arch);
+  return AI != AArch64::INVALID;
 }
 
 TEST(TargetParserTest, testAArch64Arch) {
@@ -1446,148 +1446,81 @@ TEST(TargetParserTest, testAArch64Arch) {
                               ARMBuildAttrs::CPUArch::v8_A));
 }
 
-bool testAArch64Extension(StringRef CPUName, AArch64::ArchKind AK,
+bool testAArch64Extension(StringRef CPUName, const AArch64::ArchInfo &AI,
                           StringRef ArchExt) {
-  return AArch64::getDefaultExtensions(CPUName, AK) &
+  return AArch64::getDefaultExtensions(CPUName, AI) &
          AArch64::parseArchExt(ArchExt);
 }
 
 TEST(TargetParserTest, testAArch64Extension) {
-  EXPECT_FALSE(testAArch64Extension("cortex-a34",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a35",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a53",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a55",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a55",
-                                    AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a55",
-                                    AArch64::ArchKind::INVALID, "fp16fml"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a55",
-                                    AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a57",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a72",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a73",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a75",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a75",
-                                    AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_FALSE(testAArch64Extension("cortex-a75",
-                                    AArch64::ArchKind::INVALID, "fp16fml"));
-  EXPECT_TRUE(testAArch64Extension("cortex-a75",
-                                   AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_TRUE(testAArch64Extension("cortex-r82",
-                                   AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("cortex-r82",
-                                   AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_TRUE(testAArch64Extension("cortex-r82",
-                                   AArch64::ArchKind::INVALID, "fp16fml"));
-  EXPECT_TRUE(testAArch64Extension("cortex-r82",
-                                   AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_TRUE(testAArch64Extension("cortex-r82",
-                                   AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_FALSE(testAArch64Extension("cyclone",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("exynos-m3",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m4",
-                                   AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m4",
-                                   AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m4",
-                                   AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m4",
-                                   AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m4",
-                                   AArch64::ArchKind::INVALID, "rdm"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m5",
-                                   AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m5",
-                                   AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m5",
-                                   AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m5",
-                                   AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("exynos-m5",
-                                   AArch64::ArchKind::INVALID, "rdm"));
-  EXPECT_TRUE(testAArch64Extension("falkor",
-                                   AArch64::ArchKind::INVALID, "rdm"));
-  EXPECT_FALSE(testAArch64Extension("kryo",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                    AArch64::ArchKind::INVALID, "crc"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                    AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                   AArch64::ArchKind::INVALID, "rdm"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                   AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                   AArch64::ArchKind::INVALID, "rcpc"));
-  EXPECT_TRUE(testAArch64Extension("saphira",
-                                   AArch64::ArchKind::INVALID, "profile"));
-  EXPECT_FALSE(testAArch64Extension("saphira",
-                                    AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_FALSE(testAArch64Extension("thunderx2t99",
-                                    AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_FALSE(testAArch64Extension("thunderx",
-                                    AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_FALSE(testAArch64Extension("thunderxt81",
-                                    AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_FALSE(testAArch64Extension("thunderxt83",
-                                    AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_FALSE(testAArch64Extension("thunderxt88",
-                                    AArch64::ArchKind::INVALID, "lse"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "crypto"));
-  EXPECT_FALSE(testAArch64Extension("tsv110",
-                                    AArch64::ArchKind::INVALID, "sha3"));
-  EXPECT_FALSE(testAArch64Extension("tsv110",
-                                    AArch64::ArchKind::INVALID, "sm4"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "ras"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "profile"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "fp16fml"));
-  EXPECT_TRUE(testAArch64Extension("tsv110",
-                                   AArch64::ArchKind::INVALID, "dotprod"));
-  EXPECT_TRUE(testAArch64Extension("a64fx",
-                                   AArch64::ArchKind::INVALID, "fp16"));
-  EXPECT_TRUE(testAArch64Extension("a64fx",
-                                   AArch64::ArchKind::INVALID, "sve"));
-  EXPECT_FALSE(testAArch64Extension("a64fx",
-                                   AArch64::ArchKind::INVALID, "sve2"));
-  EXPECT_TRUE(
-      testAArch64Extension("carmel", AArch64::ArchKind::INVALID, "crypto"));
-  EXPECT_TRUE(
-      testAArch64Extension("carmel", AArch64::ArchKind::INVALID, "fp16"));
-
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8A, "ras"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_1A, "ras"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_2A, "profile"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_2A, "fp16"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_2A, "fp16fml"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_3A, "fp16"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_3A, "fp16fml"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_4A, "fp16"));
-  EXPECT_FALSE(testAArch64Extension(
-      "generic", AArch64::ArchKind::ARMV8_4A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a34", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a35", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a53", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", AArch64::INVALID, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a55", AArch64::INVALID, "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", AArch64::INVALID, "dotprod"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a57", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a72", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a73", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", AArch64::INVALID, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a75", AArch64::INVALID, "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", AArch64::INVALID, "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", AArch64::INVALID, "fp16"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", AArch64::INVALID, "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", AArch64::INVALID, "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", AArch64::INVALID, "lse"));
+  EXPECT_FALSE(testAArch64Extension("cyclone", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("exynos-m3", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", AArch64::INVALID, "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", AArch64::INVALID, "fp16"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", AArch64::INVALID, "lse"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", AArch64::INVALID, "rdm"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", AArch64::INVALID, "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", AArch64::INVALID, "fp16"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", AArch64::INVALID, "lse"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", AArch64::INVALID, "rdm"));
+  EXPECT_TRUE(testAArch64Extension("falkor", AArch64::INVALID, "rdm"));
+  EXPECT_FALSE(testAArch64Extension("kryo", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "crc"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "lse"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "rdm"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "rcpc"));
+  EXPECT_TRUE(testAArch64Extension("saphira", AArch64::INVALID, "profile"));
+  EXPECT_FALSE(testAArch64Extension("saphira", AArch64::INVALID, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("thunderx2t99", AArch64::INVALID, "ras"));
+  EXPECT_FALSE(testAArch64Extension("thunderx", AArch64::INVALID, "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt81", AArch64::INVALID, "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt83", AArch64::INVALID, "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt88", AArch64::INVALID, "lse"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "crypto"));
+  EXPECT_FALSE(testAArch64Extension("tsv110", AArch64::INVALID, "sha3"));
+  EXPECT_FALSE(testAArch64Extension("tsv110", AArch64::INVALID, "sm4"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "ras"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "profile"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "fp16"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::INVALID, "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("a64fx", AArch64::INVALID, "fp16"));
+  EXPECT_TRUE(testAArch64Extension("a64fx", AArch64::INVALID, "sve"));
+  EXPECT_FALSE(testAArch64Extension("a64fx", AArch64::INVALID, "sve2"));
+  EXPECT_TRUE(testAArch64Extension("carmel", AArch64::INVALID, "crypto"));
+  EXPECT_TRUE(testAArch64Extension("carmel", AArch64::INVALID, "fp16"));
+
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8A, "ras"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_1A, "ras"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_2A, "profile"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_2A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_2A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_3A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_3A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_4A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension("generic", AArch64::ARMV8_4A, "fp16fml"));
 }
 
 TEST(TargetParserTest, AArch64ExtensionFeatures) {
@@ -1691,44 +1624,81 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
 }
 
 TEST(TargetParserTest, AArch64ArchFeatures) {
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::INVALID), "+");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8A), "+v8a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_1A), "+v8.1a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_2A), "+v8.2a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_3A), "+v8.3a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_4A), "+v8.4a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_5A), "+v8.5a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_6A), "+v8.6a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_7A), "+v8.7a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_8A), "+v8.8a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8_9A), "+v8.9a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV9A), "+v9a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV9_1A), "+v9.1a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV9_2A), "+v9.2a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV9_3A), "+v9.3a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV9_4A), "+v9.4a");
-  EXPECT_EQ(AArch64::getArchFeature(AArch64::ArchKind::ARMV8R), "+v8r");
+  EXPECT_EQ(AArch64::INVALID.ArchFeature, "+");
+  EXPECT_EQ(AArch64::ARMV8A.ArchFeature, "+v8a");
+  EXPECT_EQ(AArch64::ARMV8_1A.ArchFeature, "+v8.1a");
+  EXPECT_EQ(AArch64::ARMV8_2A.ArchFeature, "+v8.2a");
+  EXPECT_EQ(AArch64::ARMV8_3A.ArchFeature, "+v8.3a");
+  EXPECT_EQ(AArch64::ARMV8_4A.ArchFeature, "+v8.4a");
+  EXPECT_EQ(AArch64::ARMV8_5A.ArchFeature, "+v8.5a");
+  EXPECT_EQ(AArch64::ARMV8_6A.ArchFeature, "+v8.6a");
+  EXPECT_EQ(AArch64::ARMV8_7A.ArchFeature, "+v8.7a");
+  EXPECT_EQ(AArch64::ARMV8_8A.ArchFeature, "+v8.8a");
+  EXPECT_EQ(AArch64::ARMV8_9A.ArchFeature, "+v8.9a");
+  EXPECT_EQ(AArch64::ARMV9A.ArchFeature, "+v9a");
+  EXPECT_EQ(AArch64::ARMV9_1A.ArchFeature, "+v9.1a");
+  EXPECT_EQ(AArch64::ARMV9_2A.ArchFeature, "+v9.2a");
+  EXPECT_EQ(AArch64::ARMV9_3A.ArchFeature, "+v9.3a");
+  EXPECT_EQ(AArch64::ARMV9_4A.ArchFeature, "+v9.4a");
+  EXPECT_EQ(AArch64::ARMV8R.ArchFeature, "+v8r");
 }
 
-TEST(TargetParserTest, AArch64ArchV9toV8Conversion) {
-  for (auto AK : AArch64::ArchKinds) {
-    if (AK == AArch64::ArchKind::INVALID)
-      EXPECT_EQ(AK, AArch64::convertV9toV8(AK));
-    else if (AK < AArch64::ArchKind::ARMV9A)
-      EXPECT_EQ(AK, AArch64::convertV9toV8(AK));
-    else if (AK >= AArch64::ArchKind::ARMV8R)
-      EXPECT_EQ(AArch64::ArchKind::INVALID, AArch64::convertV9toV8(AK));
-    else
-      EXPECT_TRUE(AArch64::convertV9toV8(AK) < AArch64::ArchKind::ARMV9A);
+TEST(TargetParserTest, AArch64ArchPartialOrder) {
+  EXPECT_FALSE(AArch64::INVALID.implies(AArch64::INVALID));
+
+  for (const auto *A : AArch64::ArchInfos) {
+    EXPECT_EQ(*A, *A);
+    if (!(*A == *A)) {
+      EXPECT_NE(*A, *A);
+    }
+    // Comparison with invalid is always false
+    EXPECT_FALSE(A->implies(AArch64::INVALID));
+    EXPECT_FALSE(AArch64::INVALID.implies(*A));
+
+    // v8r has no relation to other valid architectures
+    if (*A != AArch64::ARMV8R) {
+      EXPECT_FALSE(A->implies(AArch64::ARMV8R));
+      EXPECT_FALSE(AArch64::ARMV8R.implies(*A));
+    }
   }
-  EXPECT_EQ(AArch64::ArchKind::ARMV8_5A,
-              AArch64::convertV9toV8(AArch64::ArchKind::ARMV9A));
-  EXPECT_EQ(AArch64::ArchKind::ARMV8_6A,
-              AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_1A));
-  EXPECT_EQ(AArch64::ArchKind::ARMV8_7A,
-              AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_2A));
-  EXPECT_EQ(AArch64::ArchKind::ARMV8_8A,
-              AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_3A));
+
+  for (const auto *A : {
+           &AArch64::ARMV8_1A,
+           &AArch64::ARMV8_2A,
+           &AArch64::ARMV8_3A,
+           &AArch64::ARMV8_4A,
+           &AArch64::ARMV8_5A,
+           &AArch64::ARMV8_6A,
+           &AArch64::ARMV8_7A,
+           &AArch64::ARMV8_8A,
+           &AArch64::ARMV8_9A,
+       })
+    EXPECT_TRUE(A->implies(AArch64::ARMV8A));
+
+  for (const auto *A : {&AArch64::ARMV9_1A, &AArch64::ARMV9_2A,
+                        &AArch64::ARMV9_3A, &AArch64::ARMV9_4A})
+    EXPECT_TRUE(A->implies(AArch64::ARMV9A));
+
+  EXPECT_TRUE(AArch64::ARMV8_1A.implies(AArch64::ARMV8A));
+  EXPECT_TRUE(AArch64::ARMV8_2A.implies(AArch64::ARMV8_1A));
+  EXPECT_TRUE(AArch64::ARMV8_3A.implies(AArch64::ARMV8_2A));
+  EXPECT_TRUE(AArch64::ARMV8_4A.implies(AArch64::ARMV8_3A));
+  EXPECT_TRUE(AArch64::ARMV8_5A.implies(AArch64::ARMV8_4A));
+  EXPECT_TRUE(AArch64::ARMV8_6A.implies(AArch64::ARMV8_5A));
+  EXPECT_TRUE(AArch64::ARMV8_7A.implies(AArch64::ARMV8_6A));
+  EXPECT_TRUE(AArch64::ARMV8_8A.implies(AArch64::ARMV8_7A));
+  EXPECT_TRUE(AArch64::ARMV8_9A.implies(AArch64::ARMV8_8A));
+
+  EXPECT_TRUE(AArch64::ARMV9_1A.implies(AArch64::ARMV9A));
+  EXPECT_TRUE(AArch64::ARMV9_2A.implies(AArch64::ARMV9_1A));
+  EXPECT_TRUE(AArch64::ARMV9_3A.implies(AArch64::ARMV9_2A));
+  EXPECT_TRUE(AArch64::ARMV9_4A.implies(AArch64::ARMV9_3A));
+
+  EXPECT_TRUE(AArch64::ARMV9A.implies(AArch64::ARMV8_5A));
+  EXPECT_TRUE(AArch64::ARMV9_1A.implies(AArch64::ARMV8_6A));
+  EXPECT_TRUE(AArch64::ARMV9_2A.implies(AArch64::ARMV8_7A));
+  EXPECT_TRUE(AArch64::ARMV9_3A.implies(AArch64::ARMV8_8A));
+  EXPECT_TRUE(AArch64::ARMV9_4A.implies(AArch64::ARMV8_9A));
 }
 
 TEST(TargetParserTest, AArch64ArchExtFeature) {


        


More information about the flang-commits mailing list