diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index b662a74e5fc68d..b3fff3c99025a5 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -239,8 +239,8 @@ enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' }; 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 + StringRef Name; // Name as supplied to -march e.g. "armv8.1-a" + StringRef ArchFeature; // Name as supplied to -target-feature, e.g. "+v8a" AArch64::ExtensionBitset DefaultExts; // bitfield of default extensions ArchExtKind @@ -289,48 +289,8 @@ struct ArchInfo { static std::optional findBySubArch(StringRef SubArch); }; -// clang-format off -inline constexpr ArchInfo ARMV8A = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", ( - AArch64::ExtensionBitset({AArch64::AEK_FP, AArch64::AEK_SIMD})), }; -inline constexpr ArchInfo ARMV8_1A = { VersionTuple{8, 1}, AProfile, "armv8.1-a", "+v8.1a", (ARMV8A.DefaultExts | - AArch64::ExtensionBitset({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::ExtensionBitset({AArch64::AEK_RAS}))}; -inline constexpr ArchInfo ARMV8_3A = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_FCMA, AArch64::AEK_JSCVT, AArch64::AEK_PAUTH, AArch64::AEK_RCPC}))}; -inline constexpr ArchInfo ARMV8_4A = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_DOTPROD}))}; -inline constexpr ArchInfo ARMV8_5A = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)}; -inline constexpr ArchInfo ARMV8_6A = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_BF16, 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 | - AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))}; -inline constexpr ArchInfo ARMV8_9A = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))}; -inline constexpr ArchInfo ARMV9A = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_FP16, AArch64::AEK_SVE, AArch64::AEK_SVE2}))}; -inline constexpr ArchInfo ARMV9_1A = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts | - AArch64::ExtensionBitset({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 | - AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))}; -inline constexpr ArchInfo ARMV9_4A = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))}; -inline constexpr ArchInfo ARMV9_5A = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_CPA}))}; -// 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", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SSBS, - AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_SB}).flip(AArch64::AEK_LSE))}; -// clang-format on - -// The set of all architectures -static constexpr std::array 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, &ARMV9_5A, &ARMV8R, -}; +#define EMIT_ARCHITECTURES +#include "llvm/TargetParser/AArch64TargetParserDef.inc" // Details of a specific CPU. struct CpuInfo { diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index b9c26e99ae0342..ba0b760ce3d738 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -792,90 +792,104 @@ def FeatureTLBIW : Extension<"tlbiw", "TLBIW", //===----------------------------------------------------------------------===// // Architectures. // -def HasV8_0aOps : SubtargetFeature<"v8a", "HasV8_0aOps", "true", - "Support ARM v8.0a instructions", [FeatureEL2VMSA, FeatureEL3]>; - -def HasV8_1aOps : SubtargetFeature<"v8.1a", "HasV8_1aOps", "true", - "Support ARM v8.1a instructions", [HasV8_0aOps, FeatureCRC, FeatureLSE, - FeatureRDM, FeaturePAN, FeatureLOR, FeatureVH]>; - -def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true", - "Support ARM v8.2a instructions", [HasV8_1aOps, FeaturePsUAO, - FeaturePAN_RWV, FeatureRAS, FeatureCCPP]>; - -def HasV8_3aOps : SubtargetFeature<"v8.3a", "HasV8_3aOps", "true", - "Support ARM v8.3a instructions", [HasV8_2aOps, FeatureRCPC, FeaturePAuth, - FeatureJS, FeatureCCIDX, FeatureComplxNum]>; - -def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true", - "Support ARM v8.4a instructions", [HasV8_3aOps, FeatureDotProd, - FeatureNV, FeatureMPAM, FeatureDIT, - FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI, - FeatureFlagM, FeatureRCPC_IMMO, FeatureLSE2]>; +class Architecture64< + int major, int minor, string profile, + string target_feature_name, + list implied_features, + list default_extensions +> : SubtargetFeature { + int Major = major; + int Minor = minor; + string Profile = profile; + + // Extensions enabled by default. Not the same as implied SubtargetFeatures. + list DefaultExts = default_extensions; +} -def HasV8_5aOps : SubtargetFeature< - "v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions", +def HasV8_0aOps : Architecture64<8, 0, "a", "v8a", + [FeatureEL2VMSA, FeatureEL3], + [FeatureFPARMv8, FeatureNEON]>; +def HasV8_1aOps : Architecture64<8, 1, "a", "v8.1a", + [HasV8_0aOps, FeatureCRC, FeatureLSE, FeatureRDM, FeaturePAN, FeatureLOR, + FeatureVH], + !listconcat(HasV8_0aOps.DefaultExts, [FeatureCRC, FeatureLSE, FeatureRDM])>; +def HasV8_2aOps : Architecture64<8, 2, "a", "v8.2a", + [HasV8_1aOps, FeaturePsUAO, FeaturePAN_RWV, FeatureRAS, FeatureCCPP], + !listconcat(HasV8_1aOps.DefaultExts, [FeatureRAS])>; +def HasV8_3aOps : Architecture64<8, 3, "a", "v8.3a", + [HasV8_2aOps, FeatureRCPC, FeaturePAuth, FeatureJS, FeatureCCIDX, + FeatureComplxNum], + !listconcat(HasV8_2aOps.DefaultExts, [FeatureComplxNum, FeatureJS, + FeaturePAuth, FeatureRCPC])>; +def HasV8_4aOps : Architecture64<8, 4, "a", "v8.4a", + [HasV8_3aOps, FeatureDotProd, FeatureNV, FeatureMPAM, FeatureDIT, + FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI, FeatureFlagM, + FeatureRCPC_IMMO, FeatureLSE2], + !listconcat(HasV8_3aOps.DefaultExts, [FeatureDotProd])>; +def HasV8_5aOps : Architecture64<8, 5, "a", "v8.5a", [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecRestrict, - FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, - FeatureBranchTargetId]>; - -def HasV8_6aOps : SubtargetFeature< - "v8.6a", "HasV8_6aOps", "true", "Support ARM v8.6a instructions", + FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, + FeatureBranchTargetId], + !listconcat(HasV8_4aOps.DefaultExts, [])>; +def HasV8_6aOps : Architecture64<8, 6, "a", "v8.6a", [HasV8_5aOps, FeatureAMVS, FeatureBF16, FeatureFineGrainedTraps, - FeatureEnhancedCounterVirtualization, FeatureMatMulInt8]>; - -def HasV8_7aOps : SubtargetFeature< - "v8.7a", "HasV8_7aOps", "true", "Support ARM v8.7a instructions", - [HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX]>; - -def HasV8_8aOps : SubtargetFeature< - "v8.8a", "HasV8_8aOps", "true", "Support ARM v8.8a instructions", - [HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI]>; - -def HasV8_9aOps : SubtargetFeature< - "v8.9a", "HasV8_9aOps", "true", "Support ARM v8.9a instructions", + FeatureEnhancedCounterVirtualization, FeatureMatMulInt8], + !listconcat(HasV8_5aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>; +def HasV8_7aOps : Architecture64<8, 7, "a", "v8.7a", + [HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX], + !listconcat(HasV8_6aOps.DefaultExts, [])>; +def HasV8_8aOps : Architecture64<8, 8, "a", "v8.8a", + [HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI], + !listconcat(HasV8_7aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>; +def HasV8_9aOps : Architecture64<8, 9, "a", "v8.9a", [HasV8_8aOps, FeatureCLRBHB, FeaturePRFM_SLC, FeatureSPECRES2, - FeatureCSSC, FeatureRASv2, FeatureCHK]>; - -def HasV9_0aOps : SubtargetFeature< - "v9a", "HasV9_0aOps", "true", "Support ARM v9a instructions", - [HasV8_5aOps, FeatureMEC, FeatureSVE2]>; - -def HasV9_1aOps : SubtargetFeature< - "v9.1a", "HasV9_1aOps", "true", "Support ARM v9.1a instructions", - [HasV8_6aOps, HasV9_0aOps]>; - -def HasV9_2aOps : SubtargetFeature< - "v9.2a", "HasV9_2aOps", "true", "Support ARM v9.2a instructions", - [HasV8_7aOps, HasV9_1aOps]>; - -def HasV9_3aOps : SubtargetFeature< - "v9.3a", "HasV9_3aOps", "true", "Support ARM v9.3a instructions", - [HasV8_8aOps, HasV9_2aOps]>; - -def HasV9_4aOps : SubtargetFeature< - "v9.4a", "HasV9_4aOps", "true", "Support ARM v9.4a instructions", - [HasV8_9aOps, HasV9_3aOps]>; - -def HasV9_5aOps : SubtargetFeature< - "v9.5a", "HasV9_5aOps", "true", "Support ARM v9.5a instructions", - [HasV9_4aOps, FeatureCPA]>; - -def HasV8_0rOps : SubtargetFeature< - "v8r", "HasV8_0rOps", "true", "Support ARM v8r instructions", - [//v8.1 - FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2, - //v8.2 - FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV, - //v8.3 - FeatureCCIDX, FeaturePAuth, FeatureRCPC, - //v8.4 - FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2, - FeatureRCPC_IMMO, - // Not mandatory in v8.0-R, but included here on the grounds that it - // only enables names of system registers - FeatureSpecRestrict - ]>; + FeatureCSSC, FeatureRASv2, FeatureCHK], + !listconcat(HasV8_8aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC, + FeatureRASv2])>; +def HasV9_0aOps : Architecture64<9, 0, "a", "v9a", + [HasV8_5aOps, FeatureMEC, FeatureSVE2], + !listconcat(HasV8_5aOps.DefaultExts, [FeatureFullFP16, FeatureSVE, + FeatureSVE2])>; +def HasV9_1aOps : Architecture64<9, 1, "a", "v9.1a", + [HasV8_6aOps, HasV9_0aOps], + !listconcat(HasV9_0aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>; +def HasV9_2aOps : Architecture64<9, 2, "a", "v9.2a", + [HasV8_7aOps, HasV9_1aOps], + !listconcat(HasV9_1aOps.DefaultExts, [])>; +def HasV9_3aOps : Architecture64<9, 3, "a", "v9.3a", + [HasV8_8aOps, HasV9_2aOps], + !listconcat(HasV9_2aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>; +def HasV9_4aOps : Architecture64<9, 4, "a", "v9.4a", + [HasV8_9aOps, HasV9_3aOps], + !listconcat(HasV9_3aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC, + FeatureRASv2])>; +def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a", + [HasV9_4aOps, FeatureCPA], + !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA])>; +def HasV8_0rOps : Architecture64<8, 0, "r", "v8r", + [ //v8.1 + FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2, + //v8.2 + FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV, + //v8.3 + FeatureCCIDX, FeaturePAuth, FeatureRCPC, + //v8.4 + FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2, + FeatureRCPC_IMMO, + // Not mandatory in v8.0-R, but included here on the grounds that it + // only enables names of system registers + FeatureSpecRestrict + ], + // For v8-R, we do not enable crypto and align with GCC that enables a more + // minimal set of optional architecture extensions. + !listconcat( + !listremove(HasV8_5aOps.DefaultExts, [FeatureLSE]), + [FeatureSSBS, FeatureFullFP16, FeatureFP16FML, FeatureSB] + )>; //===----------------------------------------------------------------------===// // Access to privileged registers diff --git a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp index 0e90f57af49389..491011643bbfb1 100644 --- a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp @@ -13,9 +13,12 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Format.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include +#include using namespace llvm; @@ -112,6 +115,68 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { << "#undef EMIT_EXTENSIONS\n" << "#endif // EMIT_EXTENSIONS\n" << "\n"; + + // Emit architecture information + OS << "#ifdef EMIT_ARCHITECTURES\n"; + + auto Architectures = RK.getAllDerivedDefinitionsIfDefined("Architecture64"); + std::vector CppSpellings; + for (const Record *Rec : Architectures) { + const int Major = Rec->getValueAsInt("Major"); + const int Minor = Rec->getValueAsInt("Minor"); + const std::string ProfileLower = Rec->getValueAsString("Profile").str(); + const std::string ProfileUpper = Rec->getValueAsString("Profile").upper(); + + if (ProfileLower != "a" && ProfileLower != "r") + PrintFatalError(Rec->getLoc(), + "error: Profile must be one of 'a' or 'r', got '" + + ProfileLower + "'"); + + // Name of the object in C++ + const std::string CppSpelling = + Minor == 0 ? "ARMV" + std::to_string(Major) + ProfileUpper.c_str() + : "ARMV" + std::to_string(Major) + "_" + + std::to_string(Minor) + ProfileUpper.c_str(); + OS << "inline constexpr ArchInfo " << CppSpelling << " = {\n"; + CppSpellings.push_back(CppSpelling); + + OS << llvm::format(" VersionTuple{%d, %d},\n", Major, Minor); + OS << llvm::format(" %sProfile,\n", ProfileUpper.c_str()); + + // Name as spelled for -march. + if (Minor == 0) + OS << llvm::format(" \"armv%d-%s\",\n", Major, ProfileLower.c_str()); + else + OS << llvm::format(" \"armv%d.%d-%s\",\n", Major, Minor, + ProfileLower.c_str()); + + // SubtargetFeature::Name, used for -target-feature. Here the "+" is added. + const auto TargetFeatureName = Rec->getValueAsString("Name"); + OS << " \"+" << TargetFeatureName << "\",\n"; + + // Construct the list of default extensions + OS << " (AArch64::ExtensionBitset({"; + for (auto *E : Rec->getValueAsListOfDefs("DefaultExts")) { + // Only process subclasses of Extension + OS << "AArch64::" << E->getValueAsString("ArchExtKindSpelling").upper() + << ", "; + } + OS << "}))\n"; + + OS << "};\n"; + } + + OS << "\n" + << "/// The set of all architectures\n" + << "static constexpr std::array ArchInfos = {\n"; + for (auto CppSpelling : CppSpellings) + OS << " &" << CppSpelling << ",\n"; + OS << "};\n"; + + OS << "#undef EMIT_ARCHITECTURES\n" + << "#endif // EMIT_ARCHITECTURES\n" + << "\n"; } static TableGen::Emitter::Opt