// 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,
{"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
// 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;
}
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)};
// 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.
(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.
// 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);
#include "llvm/TargetParser/Triple.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include <optional>
#include <string>
using namespace llvm;
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);
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,
// 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) {
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) {
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());
}
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");
}
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) {