[NFC][AArch64] Use optional returns in target parser instead of 'invalid' objects
authorLucas Prates <lucas.prates@arm.com>
Mon, 23 Jan 2023 11:12:38 +0000 (11:12 +0000)
committerLucas Prates <lucas.prates@arm.com>
Fri, 27 Jan 2023 12:35:58 +0000 (12:35 +0000)
This updates the parsing methods in AArch64's Target Parser to make use
of optional returns instead of "invalid" enum values, making the API's
behaviour clearer.

Reviewed By: lenary, tmatheson

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

clang/lib/Basic/Targets/AArch64.cpp
clang/lib/Driver/ToolChains/Arch/AArch64.cpp
llvm/include/llvm/TargetParser/AArch64TargetParser.h
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/TargetParser/AArch64TargetParser.cpp
llvm/unittests/TargetParser/TargetParserTest.cpp

index dfed95f..5971489 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/AArch64TargetParser.h"
 #include "llvm/Support/ARMTargetParserCommon.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
 #include <optional>
 
 using namespace clang;
@@ -223,8 +224,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
 }
 
 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
-  return Name == "generic" ||
-         llvm::AArch64::parseCpu(Name).Arch != llvm::AArch64::INVALID;
+  return Name == "generic" || llvm::AArch64::parseCpu(Name);
 }
 
 bool AArch64TargetInfo::setCPU(const std::string &Name) {
@@ -681,19 +681,19 @@ void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
   Features[Name] = Enabled;
   // If the feature is an architecture feature (like v8.2a), add all previous
   // architecture versions and any dependant target features.
-  const llvm::AArch64::ArchInfo &ArchInfo =
+  const std::optional<llvm::AArch64::ArchInfo> ArchInfo =
       llvm::AArch64::ArchInfo::findBySubArch(Name);
 
-  if (ArchInfo == llvm::AArch64::INVALID)
+  if (!ArchInfo)
     return; // Not an architecure, nothing more to do.
 
   for (const auto *OtherArch : llvm::AArch64::ArchInfos)
-    if (ArchInfo.implies(*OtherArch))
+    if (ArchInfo->implies(*OtherArch))
       Features[OtherArch->getSubArch()] = Enabled;
 
   // Set any features implied by the architecture
   uint64_t Extensions =
-      llvm::AArch64::getDefaultExtensions("generic", ArchInfo);
+      llvm::AArch64::getDefaultExtensions("generic", *ArchInfo);
   std::vector<StringRef> CPUFeats;
   if (llvm::AArch64::getExtensionFeatures(Extensions, CPUFeats)) {
     for (auto F : CPUFeats) {
@@ -949,9 +949,9 @@ bool AArch64TargetInfo::initFeatureMap(
     const std::vector<std::string> &FeaturesVec) const {
   std::vector<std::string> UpdatedFeaturesVec;
   // Parse the CPU and add any implied features.
-  const llvm::AArch64::ArchInfo &Arch = llvm::AArch64::parseCpu(CPU).Arch;
-  if (Arch != llvm::AArch64::INVALID) {
-    uint64_t Exts = llvm::AArch64::getDefaultExtensions(CPU, Arch);
+  std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu(CPU);
+  if (CpuInfo) {
+    uint64_t Exts = llvm::AArch64::getDefaultExtensions(CPU, CpuInfo->Arch);
     std::vector<StringRef> CPUFeats;
     llvm::AArch64::getExtensionFeatures(Exts, CPUFeats);
     for (auto F : CPUFeats) {
@@ -1033,13 +1033,14 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
       FoundArch = true;
       std::pair<StringRef, StringRef> Split =
           Feature.split("=").second.trim().split("+");
-      const llvm::AArch64::ArchInfo &AI = llvm::AArch64::parseArch(Split.first);
+      const std::optional<llvm::AArch64::ArchInfo> AI =
+          llvm::AArch64::parseArch(Split.first);
 
       // Parse the architecture version, adding the required features to
       // Ret.Features.
-      if (AI == llvm::AArch64::INVALID)
+      if (!AI)
         continue;
-      Ret.Features.push_back(AI.ArchFeature.str());
+      Ret.Features.push_back(AI->ArchFeature.str());
       // Add any extra features, after the +
       SplitAndAddFeatures(Split.second, Ret.Features);
     } else if (Feature.startswith("cpu=")) {
index 2c559cc..81b0245 100644 (file)
@@ -123,8 +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;
   const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A;
-  CPU = llvm::AArch64::resolveCPUAlias(Split.first);
 
   if (CPU == "native")
     CPU = llvm::sys::getHostCPUName();
@@ -132,9 +132,12 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
   if (CPU == "generic") {
     Features.push_back("+neon");
   } else {
-    ArchInfo = &llvm::AArch64::parseCpu(CPU).Arch;
-    if (*ArchInfo == llvm::AArch64::INVALID)
+    const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
+        llvm::AArch64::parseCpu(CPU);
+    if (!CpuInfo)
       return false;
+    ArchInfo = &CpuInfo->Arch;
+
     Features.push_back(ArchInfo->ArchFeature);
 
     uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, *ArchInfo);
@@ -156,11 +159,11 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
   std::string MarchLowerCase = March.lower();
   std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
 
-  const llvm::AArch64::ArchInfo *ArchInfo =
-      &llvm::AArch64::parseArch(Split.first);
+  std::optional <llvm::AArch64::ArchInfo> ArchInfo =
+      llvm::AArch64::parseArch(Split.first);
   if (Split.first == "native")
-    ArchInfo = &llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
-  if (*ArchInfo == llvm::AArch64::INVALID)
+    ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
+  if (!ArchInfo)
     return false;
   Features.push_back(ArchInfo->ArchFeature);
 
index 16bf393..ea06d7d 100644 (file)
@@ -91,7 +91,6 @@ enum CPUFeatures {
 // feature name (though the canonical reference for those is AArch64.td)
 // clang-format off
 enum ArchExtKind : uint64_t {
-  AEK_INVALID =     0,
   AEK_NONE =        1,
   AEK_CRC =         1 << 1,  // FEAT_CRC32
   AEK_CRYPTO =      1 << 2,
@@ -252,7 +251,6 @@ inline constexpr ExtensionInfo Extensions[] = {
     {"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
 
@@ -280,12 +278,12 @@ struct ArchInfo {
   //       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
+  // v8r has 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
+      return false; // ARMV8R
     if (this->Version.getMajor() == Other.Version.getMajor()) {
       return this->Version > Other.Version;
     }
@@ -300,11 +298,10 @@ struct ArchInfo {
   StringRef getSubArch() const { return ArchFeature.substr(1); }
 
   // Search for ArchInfo by SubArch name
-  static const ArchInfo &findBySubArch(StringRef SubArch);
+  static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
 };
 
 // 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_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)};
@@ -325,10 +322,10 @@ inline constexpr ArchInfo ARMV8R    = { VersionTuple{8, 0}, RProfile, "armv8-r",
 // clang-format on
 
 // 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,
+static constexpr std::array<const ArchInfo *, 16> ArchInfos = {
+    &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,
 };
 
 // Details of a specific CPU.
@@ -495,8 +492,6 @@ inline constexpr CpuInfo CpuInfos[] = {
      (AArch64::AEK_FP16 | AArch64::AEK_RAND | AArch64::AEK_SM4 |
       AArch64::AEK_SHA3 | AArch64::AEK_SHA2 | AArch64::AEK_AES |
       AArch64::AEK_MTE | AArch64::AEK_SB | AArch64::AEK_SSBS)},
-    // Invalid CPU
-    {"invalid", INVALID, (AArch64::AEK_INVALID)},
 };
 
 // An alias for a CPU.
@@ -516,13 +511,13 @@ StringRef resolveCPUAlias(StringRef CPU);
 // Information by Name
 uint64_t getDefaultExtensions(StringRef CPU, const ArchInfo &AI);
 void getFeatureOption(StringRef Name, std::string &Feature);
-const ArchInfo &getArchForCpu(StringRef CPU);
+std::optional<ArchInfo> getArchForCpu(StringRef CPU);
 
 // Parser
-const ArchInfo &parseArch(StringRef Arch);
-ArchExtKind parseArchExt(StringRef ArchExt);
+std::optional<ArchInfo> parseArch(StringRef Arch);
+std::optional<ExtensionInfo> parseArchExtension(StringRef Extension);
 // Given the name of a CPU or alias, return the correponding CpuInfo.
-const CpuInfo &parseCpu(StringRef Name);
+std::optional<CpuInfo> parseCpu(StringRef Name);
 // Used by target parser tests
 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
 
index 993ce48..840f792 100644 (file)
@@ -51,6 +51,7 @@
 #include "llvm/Support/AArch64TargetParser.h"
 #include "llvm/Support/TargetParser.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
 #include <cassert>
 #include <cctype>
 #include <cstdint>
@@ -6880,8 +6881,8 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
   std::tie(Arch, ExtensionString) =
       getParser().parseStringToEndOfStatement().trim().split('+');
 
-  const AArch64::ArchInfo &ArchInfo = AArch64::parseArch(Arch);
-  if (ArchInfo == AArch64::INVALID)
+  std::optional<AArch64::ArchInfo> ArchInfo = AArch64::parseArch(Arch);
+  if (!ArchInfo)
     return Error(ArchLoc, "unknown arch name");
 
   if (parseToken(AsmToken::EndOfStatement))
@@ -6889,9 +6890,9 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
 
   // Get the architecture and extension features.
   std::vector<StringRef> AArch64Features;
-  AArch64Features.push_back(ArchInfo.ArchFeature);
+  AArch64Features.push_back(ArchInfo->ArchFeature);
   AArch64::getExtensionFeatures(
-      AArch64::getDefaultExtensions("generic", ArchInfo), AArch64Features);
+      AArch64::getDefaultExtensions("generic", *ArchInfo), AArch64Features);
 
   MCSubtargetInfo &STI = copySTI();
   std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
@@ -6902,7 +6903,7 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
   if (!ExtensionString.empty())
     ExtensionString.split(RequestedExtensions, '+');
 
-  ExpandCryptoAEK(ArchInfo, RequestedExtensions);
+  ExpandCryptoAEK(*ArchInfo, RequestedExtensions);
 
   FeatureBitset Features = STI.getFeatureBits();
   for (auto Name : RequestedExtensions) {
@@ -6987,19 +6988,17 @@ bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
   if (!ExtensionString.empty())
     ExtensionString.split(RequestedExtensions, '+');
 
-  // FIXME This is using tablegen data, but should be moved to ARMTargetParser
-  // once that is tablegen'ed
-  if (!getSTI().isCPUStringValid(CPU)) {
+  const std::optional<llvm::AArch64::ArchInfo> CpuArch = llvm::AArch64::getArchForCpu(CPU);
+  if (!CpuArch) {
     Error(CurLoc, "unknown CPU name");
     return false;
   }
+  ExpandCryptoAEK(*CpuArch, RequestedExtensions);
 
   MCSubtargetInfo &STI = copySTI();
   STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
   CurLoc = incrementLoc(CurLoc, CPU.size());
 
-  ExpandCryptoAEK(llvm::AArch64::getArchForCpu(CPU), RequestedExtensions);
-
   for (auto Name : RequestedExtensions) {
     // Advance source location past '+'.
     CurLoc = incrementLoc(CurLoc, 1);
index 41d5c25..7dd0c45 100644 (file)
@@ -31,8 +31,11 @@ uint64_t AArch64::getDefaultExtensions(StringRef CPU,
     return AI.DefaultExts;
 
   // Note: this now takes cpu aliases into account
-  const CpuInfo &Cpu = parseCpu(CPU);
-  return Cpu.Arch.DefaultExts | Cpu.DefaultExtensions;
+  std::optional<CpuInfo> Cpu = parseCpu(CPU);
+  if (!Cpu)
+    return AI.DefaultExts;
+
+  return Cpu->Arch.DefaultExts | Cpu->DefaultExtensions;
 }
 
 void AArch64::getFeatureOption(StringRef Name, std::string &Feature) {
@@ -45,20 +48,22 @@ void AArch64::getFeatureOption(StringRef Name, std::string &Feature) {
   Feature = Name.str();
 }
 
-const AArch64::ArchInfo &AArch64::getArchForCpu(StringRef CPU) {
+std::optional<AArch64::ArchInfo> AArch64::getArchForCpu(StringRef CPU) {
   if (CPU == "generic")
     return ARMV8A;
 
   // Note: this now takes cpu aliases into account
-  const CpuInfo &Cpu = parseCpu(CPU);
-  return Cpu.Arch;
+  std::optional<CpuInfo> Cpu = parseCpu(CPU);
+  if (!Cpu)
+    return {};
+  return Cpu->Arch;
 }
 
-const AArch64::ArchInfo &AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
+std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
   for (const auto *A : AArch64::ArchInfos)
     if (A->getSubArch() == SubArch)
       return *A;
-  return AArch64::INVALID;
+  return {};
 }
 
 uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
@@ -75,9 +80,6 @@ uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
 
 bool AArch64::getExtensionFeatures(uint64_t InputExts,
                                    std::vector<StringRef> &Features) {
-  if (InputExts == AArch64::AEK_INVALID)
-    return false;
-
   for (const auto &E : Extensions)
     /* INVALID and NONE have no feature name. */
     if ((InputExts & E.ID) && !E.Feature.empty())
@@ -110,7 +112,6 @@ StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
 
 void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
   for (const auto &C : CpuInfos)
-    if (C.Arch != INVALID)
       Values.push_back(C.Name);
 
   for (const auto &Alias : CpuAliases)
@@ -123,28 +124,28 @@ bool AArch64::isX18ReservedByDefault(const Triple &TT) {
 }
 
 // Allows partial match, ex. "v8a" matches "armv8a".
-const AArch64::ArchInfo &AArch64::parseArch(StringRef Arch) {
+std::optional<AArch64::ArchInfo> AArch64::parseArch(StringRef Arch) {
   Arch = llvm::ARM::getCanonicalArchName(Arch);
   if (checkArchVersion(Arch) < 8)
-    return AArch64::INVALID;
+    return {};
 
   StringRef Syn = llvm::ARM::getArchSynonym(Arch);
   for (const auto *A : ArchInfos) {
     if (A->Name.endswith(Syn))
       return *A;
   }
-  return AArch64::INVALID;
+  return {};
 }
 
-AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
+std::optional<AArch64::ExtensionInfo> AArch64::parseArchExtension(StringRef ArchExt) {
   for (const auto &A : Extensions) {
     if (ArchExt == A.Name)
-      return static_cast<ArchExtKind>(A.ID);
+      return A;
   }
-  return AArch64::AEK_INVALID;
+  return {};
 }
 
-const AArch64::CpuInfo &AArch64::parseCpu(StringRef Name) {
+std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
   // Resolve aliases first.
   Name = resolveCPUAlias(Name);
 
@@ -153,7 +154,5 @@ const AArch64::CpuInfo &AArch64::parseCpu(StringRef Name) {
     if (Name == C.Name)
       return C;
 
-  // "generic" returns invalid.
-  assert(Name != "invalid" && "Unexpected recursion.");
-  return parseCpu("invalid");
+  return {};
 }
index 2d96716..2970e01 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include <optional>
 #include <string>
 
 using namespace llvm;
@@ -961,11 +962,12 @@ class AArch64CPUTestFixture
 TEST_P(AArch64CPUTestFixture, testAArch64CPU) {
   ARMCPUTestParams params = GetParam();
 
-  const AArch64::ArchInfo &AI = AArch64::parseCpu(params.CPUName).Arch;
-  EXPECT_EQ(params.ExpectedArch, AI.Name);
+  const std::optional<AArch64::CpuInfo> Cpu = AArch64::parseCpu(params.CPUName);
+  EXPECT_TRUE(Cpu);
+  EXPECT_EQ(params.ExpectedArch, Cpu->Arch.Name);
 
   uint64_t default_extensions =
-      AArch64::getDefaultExtensions(params.CPUName, AI);
+      AArch64::getDefaultExtensions(params.CPUName, Cpu->Arch);
   EXPECT_PRED_FORMAT2(
       AssertSameExtensionFlags<ARM::ISAKind::AARCH64>(params.CPUName),
       params.ExpectedFlags, default_extensions);
@@ -974,10 +976,6 @@ TEST_P(AArch64CPUTestFixture, testAArch64CPU) {
 INSTANTIATE_TEST_SUITE_P(
     AArch64CPUTests, AArch64CPUTestFixture,
     ::testing::Values(
-        ARMCPUTestParams("invalid", "invalid", "invalid", AArch64::AEK_NONE,
-                         ""),
-        ARMCPUTestParams("generic", "invalid", "none", AArch64::AEK_NONE, ""),
-
         ARMCPUTestParams("cortex-a34", "armv8-a", "crypto-neon-fp-armv8",
                          AArch64::AEK_CRC | AArch64::AEK_CRYPTO |
                              AArch64::AEK_FP | AArch64::AEK_SIMD,
@@ -1425,14 +1423,14 @@ TEST(TargetParserTest, testAArch64CPUArchList) {
   // valid, and match the expected 'magic' count.
   EXPECT_EQ(List.size(), NumAArch64CPUArchs);
   for(StringRef CPU : List) {
-    EXPECT_NE(AArch64::parseCpu(CPU).Arch, AArch64::INVALID);
+    EXPECT_TRUE(AArch64::parseCpu(CPU));
   }
 }
 
 bool testAArch64Arch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,
                      unsigned ArchAttr) {
-  const AArch64::ArchInfo &AI = AArch64::parseArch(Arch);
-  return AI != AArch64::INVALID;
+  const std::optional<AArch64::ArchInfo> AI = AArch64::parseArch(Arch);
+  return AI.has_value();
 }
 
 TEST(TargetParserTest, testAArch64Arch) {
@@ -1468,81 +1466,92 @@ TEST(TargetParserTest, testAArch64Arch) {
                               ARMBuildAttrs::CPUArch::v8_A));
 }
 
-bool testAArch64Extension(StringRef CPUName, const AArch64::ArchInfo &AI,
-                          StringRef ArchExt) {
-  return AArch64::getDefaultExtensions(CPUName, AI) &
-         AArch64::parseArchExt(ArchExt);
+bool testAArch64Extension(StringRef CPUName, StringRef ArchExt) {
+  std::optional<AArch64::ExtensionInfo> Extension =
+      AArch64::parseArchExtension(ArchExt);
+  if (!Extension)
+    return false;
+  std::optional<AArch64::CpuInfo> CpuInfo = AArch64::parseCpu(CPUName);
+  return (CpuInfo->Arch.DefaultExts | CpuInfo->DefaultExtensions) & Extension->ID;
+}
+
+bool testAArch64Extension(const AArch64::ArchInfo &AI, StringRef ArchExt) {
+  std::optional<AArch64::ExtensionInfo> Extension =
+      AArch64::parseArchExtension(ArchExt);
+  if (!Extension)
+    return false;
+  return AI.DefaultExts & Extension->ID;
 }
 
 TEST(TargetParserTest, testAArch64Extension) {
-  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"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a34", "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a35", "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a53", "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", "fp16"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a55", "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a55", "dotprod"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a57", "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a72", "ras"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a73", "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", "fp16"));
+  EXPECT_FALSE(testAArch64Extension("cortex-a75", "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-a75", "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", "ras"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", "fp16"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("cortex-r82", "lse"));
+  EXPECT_FALSE(testAArch64Extension("cyclone", "ras"));
+  EXPECT_FALSE(testAArch64Extension("exynos-m3", "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", "fp16"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", "lse"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m4", "rdm"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", "fp16"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", "lse"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", "ras"));
+  EXPECT_TRUE(testAArch64Extension("exynos-m5", "rdm"));
+  EXPECT_TRUE(testAArch64Extension("falkor", "rdm"));
+  EXPECT_FALSE(testAArch64Extension("kryo", "ras"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "crc"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "lse"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "rdm"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "ras"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "rcpc"));
+  EXPECT_TRUE(testAArch64Extension("saphira", "profile"));
+  EXPECT_FALSE(testAArch64Extension("saphira", "fp16"));
+  EXPECT_FALSE(testAArch64Extension("thunderx2t99", "ras"));
+  EXPECT_FALSE(testAArch64Extension("thunderx", "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt81", "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt83", "lse"));
+  EXPECT_FALSE(testAArch64Extension("thunderxt88", "lse"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "crypto"));
+  EXPECT_FALSE(testAArch64Extension("tsv110", "sha3"));
+  EXPECT_FALSE(testAArch64Extension("tsv110", "sm4"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "ras"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "profile"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "fp16"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "fp16fml"));
+  EXPECT_TRUE(testAArch64Extension("tsv110", "dotprod"));
+  EXPECT_TRUE(testAArch64Extension("a64fx", "fp16"));
+  EXPECT_TRUE(testAArch64Extension("a64fx", "sve"));
+  EXPECT_FALSE(testAArch64Extension("a64fx", "sve2"));
+  EXPECT_TRUE(testAArch64Extension("carmel", "crypto"));
+  EXPECT_TRUE(testAArch64Extension("carmel", "fp16"));
+
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8A, "ras"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_1A, "ras"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "profile"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_3A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_3A, "fp16fml"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16"));
+  EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16fml"));
 }
 
 TEST(TargetParserTest, AArch64ExtensionFeatures) {
@@ -1574,9 +1583,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
   for (auto Ext : Extensions)
     ExtVal |= Ext;
 
-  // INVALID and NONE have no feature names.
-  EXPECT_FALSE(AArch64::getExtensionFeatures(AArch64::AEK_INVALID, Features));
-  EXPECT_TRUE(!Features.size());
+  // NONE has no feature names.
   // We return True here because NONE is a valid choice.
   EXPECT_TRUE(AArch64::getExtensionFeatures(AArch64::AEK_NONE, Features));
   EXPECT_TRUE(!Features.size());
@@ -1648,7 +1655,6 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
 }
 
 TEST(TargetParserTest, AArch64ArchFeatures) {
-  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");
@@ -1668,13 +1674,8 @@ TEST(TargetParserTest, AArch64ArchFeatures) {
 }
 
 TEST(TargetParserTest, AArch64ArchPartialOrder) {
-  EXPECT_FALSE(AArch64::INVALID.implies(AArch64::INVALID));
-
   for (const auto *A : AArch64::ArchInfos) {
     EXPECT_EQ(*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) {