Skip to content

Commit 72a8953

Browse files
[AArch64][TargetParser] move ArchInfo into tablegen [NFC] (#92037)
This moves the architecture version, profile and extension information into tablegen, and generates the TargetParser ArchInfo objects from this data. There are two lists of "dependencies" defined for each architecture: the SubtargetFeature::Implies which controls which features are automatically enabled in the backend when the corresponding architecture SubtargetFeature is enabled; and the list of Extensions which are enabled by default for this architecture. As far as I can tell, the idea here is that the SubtargetFeature models the mandatory dependencies (although they can still be disabled if desired) while the default extensions models the typical use case for that architecture.
1 parent 51403ad commit 72a8953

File tree

3 files changed

+163
-124
lines changed

3 files changed

+163
-124
lines changed

llvm/include/llvm/TargetParser/AArch64TargetParser.h

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
239239
struct ArchInfo {
240240
VersionTuple Version; // Architecture version, major + minor.
241241
ArchProfile Profile; // Architecuture profile
242-
StringRef Name; // Human readable name, e.g. "armv8.1-a"
243-
StringRef ArchFeature; // Command line feature flag, e.g. +v8a
242+
StringRef Name; // Name as supplied to -march e.g. "armv8.1-a"
243+
StringRef ArchFeature; // Name as supplied to -target-feature, e.g. "+v8a"
244244
AArch64::ExtensionBitset
245245
DefaultExts; // bitfield of default extensions ArchExtKind
246246

@@ -289,48 +289,8 @@ struct ArchInfo {
289289
static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
290290
};
291291

292-
// clang-format off
293-
inline constexpr ArchInfo ARMV8A = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", (
294-
AArch64::ExtensionBitset({AArch64::AEK_FP, AArch64::AEK_SIMD})), };
295-
inline constexpr ArchInfo ARMV8_1A = { VersionTuple{8, 1}, AProfile, "armv8.1-a", "+v8.1a", (ARMV8A.DefaultExts |
296-
AArch64::ExtensionBitset({AArch64::AEK_CRC, AArch64::AEK_LSE, AArch64::AEK_RDM}))};
297-
inline constexpr ArchInfo ARMV8_2A = { VersionTuple{8, 2}, AProfile, "armv8.2-a", "+v8.2a", (ARMV8_1A.DefaultExts |
298-
AArch64::ExtensionBitset({AArch64::AEK_RAS}))};
299-
inline constexpr ArchInfo ARMV8_3A = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts |
300-
AArch64::ExtensionBitset({AArch64::AEK_FCMA, AArch64::AEK_JSCVT, AArch64::AEK_PAUTH, AArch64::AEK_RCPC}))};
301-
inline constexpr ArchInfo ARMV8_4A = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts |
302-
AArch64::ExtensionBitset({AArch64::AEK_DOTPROD}))};
303-
inline constexpr ArchInfo ARMV8_5A = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)};
304-
inline constexpr ArchInfo ARMV8_6A = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts |
305-
AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))};
306-
inline constexpr ArchInfo ARMV8_7A = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)};
307-
inline constexpr ArchInfo ARMV8_8A = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts |
308-
AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))};
309-
inline constexpr ArchInfo ARMV8_9A = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts |
310-
AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))};
311-
inline constexpr ArchInfo ARMV9A = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts |
312-
AArch64::ExtensionBitset({AArch64::AEK_FP16, AArch64::AEK_SVE, AArch64::AEK_SVE2}))};
313-
inline constexpr ArchInfo ARMV9_1A = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts |
314-
AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))};
315-
inline constexpr ArchInfo ARMV9_2A = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)};
316-
inline constexpr ArchInfo ARMV9_3A = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts |
317-
AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))};
318-
inline constexpr ArchInfo ARMV9_4A = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts |
319-
AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))};
320-
inline constexpr ArchInfo ARMV9_5A = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts |
321-
AArch64::ExtensionBitset({AArch64::AEK_CPA}))};
322-
// For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions.
323-
inline constexpr ArchInfo ARMV8R = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", (ARMV8_5A.DefaultExts |
324-
AArch64::ExtensionBitset({AArch64::AEK_SSBS,
325-
AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_SB}).flip(AArch64::AEK_LSE))};
326-
// clang-format on
327-
328-
// The set of all architectures
329-
static constexpr std::array<const ArchInfo *, 17> ArchInfos = {
330-
&ARMV8A, &ARMV8_1A, &ARMV8_2A, &ARMV8_3A, &ARMV8_4A, &ARMV8_5A,
331-
&ARMV8_6A, &ARMV8_7A, &ARMV8_8A, &ARMV8_9A, &ARMV9A, &ARMV9_1A,
332-
&ARMV9_2A, &ARMV9_3A, &ARMV9_4A, &ARMV9_5A, &ARMV8R,
333-
};
292+
#define EMIT_ARCHITECTURES
293+
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
334294

335295
// Details of a specific CPU.
336296
struct CpuInfo {

llvm/lib/Target/AArch64/AArch64Features.td

Lines changed: 94 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -792,90 +792,104 @@ def FeatureTLBIW : Extension<"tlbiw", "TLBIW",
792792
//===----------------------------------------------------------------------===//
793793
// Architectures.
794794
//
795-
def HasV8_0aOps : SubtargetFeature<"v8a", "HasV8_0aOps", "true",
796-
"Support ARM v8.0a instructions", [FeatureEL2VMSA, FeatureEL3]>;
797-
798-
def HasV8_1aOps : SubtargetFeature<"v8.1a", "HasV8_1aOps", "true",
799-
"Support ARM v8.1a instructions", [HasV8_0aOps, FeatureCRC, FeatureLSE,
800-
FeatureRDM, FeaturePAN, FeatureLOR, FeatureVH]>;
801-
802-
def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true",
803-
"Support ARM v8.2a instructions", [HasV8_1aOps, FeaturePsUAO,
804-
FeaturePAN_RWV, FeatureRAS, FeatureCCPP]>;
805-
806-
def HasV8_3aOps : SubtargetFeature<"v8.3a", "HasV8_3aOps", "true",
807-
"Support ARM v8.3a instructions", [HasV8_2aOps, FeatureRCPC, FeaturePAuth,
808-
FeatureJS, FeatureCCIDX, FeatureComplxNum]>;
809-
810-
def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true",
811-
"Support ARM v8.4a instructions", [HasV8_3aOps, FeatureDotProd,
812-
FeatureNV, FeatureMPAM, FeatureDIT,
813-
FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI,
814-
FeatureFlagM, FeatureRCPC_IMMO, FeatureLSE2]>;
795+
class Architecture64<
796+
int major, int minor, string profile,
797+
string target_feature_name,
798+
list<SubtargetFeature> implied_features,
799+
list<Extension> default_extensions
800+
> : SubtargetFeature<target_feature_name,
801+
"HasV" # major # "_" # minor # profile # "Ops", "true",
802+
"Support ARM " # target_feature_name # " architecture",
803+
implied_features
804+
> {
805+
int Major = major;
806+
int Minor = minor;
807+
string Profile = profile;
808+
809+
// Extensions enabled by default. Not the same as implied SubtargetFeatures.
810+
list<Extension> DefaultExts = default_extensions;
811+
}
815812

816-
def HasV8_5aOps : SubtargetFeature<
817-
"v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions",
813+
def HasV8_0aOps : Architecture64<8, 0, "a", "v8a",
814+
[FeatureEL2VMSA, FeatureEL3],
815+
[FeatureFPARMv8, FeatureNEON]>;
816+
def HasV8_1aOps : Architecture64<8, 1, "a", "v8.1a",
817+
[HasV8_0aOps, FeatureCRC, FeatureLSE, FeatureRDM, FeaturePAN, FeatureLOR,
818+
FeatureVH],
819+
!listconcat(HasV8_0aOps.DefaultExts, [FeatureCRC, FeatureLSE, FeatureRDM])>;
820+
def HasV8_2aOps : Architecture64<8, 2, "a", "v8.2a",
821+
[HasV8_1aOps, FeaturePsUAO, FeaturePAN_RWV, FeatureRAS, FeatureCCPP],
822+
!listconcat(HasV8_1aOps.DefaultExts, [FeatureRAS])>;
823+
def HasV8_3aOps : Architecture64<8, 3, "a", "v8.3a",
824+
[HasV8_2aOps, FeatureRCPC, FeaturePAuth, FeatureJS, FeatureCCIDX,
825+
FeatureComplxNum],
826+
!listconcat(HasV8_2aOps.DefaultExts, [FeatureComplxNum, FeatureJS,
827+
FeaturePAuth, FeatureRCPC])>;
828+
def HasV8_4aOps : Architecture64<8, 4, "a", "v8.4a",
829+
[HasV8_3aOps, FeatureDotProd, FeatureNV, FeatureMPAM, FeatureDIT,
830+
FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI, FeatureFlagM,
831+
FeatureRCPC_IMMO, FeatureLSE2],
832+
!listconcat(HasV8_3aOps.DefaultExts, [FeatureDotProd])>;
833+
def HasV8_5aOps : Architecture64<8, 5, "a", "v8.5a",
818834
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecRestrict,
819-
FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist,
820-
FeatureBranchTargetId]>;
821-
822-
def HasV8_6aOps : SubtargetFeature<
823-
"v8.6a", "HasV8_6aOps", "true", "Support ARM v8.6a instructions",
835+
FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist,
836+
FeatureBranchTargetId],
837+
!listconcat(HasV8_4aOps.DefaultExts, [])>;
838+
def HasV8_6aOps : Architecture64<8, 6, "a", "v8.6a",
824839
[HasV8_5aOps, FeatureAMVS, FeatureBF16, FeatureFineGrainedTraps,
825-
FeatureEnhancedCounterVirtualization, FeatureMatMulInt8]>;
826-
827-
def HasV8_7aOps : SubtargetFeature<
828-
"v8.7a", "HasV8_7aOps", "true", "Support ARM v8.7a instructions",
829-
[HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX]>;
830-
831-
def HasV8_8aOps : SubtargetFeature<
832-
"v8.8a", "HasV8_8aOps", "true", "Support ARM v8.8a instructions",
833-
[HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI]>;
834-
835-
def HasV8_9aOps : SubtargetFeature<
836-
"v8.9a", "HasV8_9aOps", "true", "Support ARM v8.9a instructions",
840+
FeatureEnhancedCounterVirtualization, FeatureMatMulInt8],
841+
!listconcat(HasV8_5aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>;
842+
def HasV8_7aOps : Architecture64<8, 7, "a", "v8.7a",
843+
[HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX],
844+
!listconcat(HasV8_6aOps.DefaultExts, [])>;
845+
def HasV8_8aOps : Architecture64<8, 8, "a", "v8.8a",
846+
[HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI],
847+
!listconcat(HasV8_7aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>;
848+
def HasV8_9aOps : Architecture64<8, 9, "a", "v8.9a",
837849
[HasV8_8aOps, FeatureCLRBHB, FeaturePRFM_SLC, FeatureSPECRES2,
838-
FeatureCSSC, FeatureRASv2, FeatureCHK]>;
839-
840-
def HasV9_0aOps : SubtargetFeature<
841-
"v9a", "HasV9_0aOps", "true", "Support ARM v9a instructions",
842-
[HasV8_5aOps, FeatureMEC, FeatureSVE2]>;
843-
844-
def HasV9_1aOps : SubtargetFeature<
845-
"v9.1a", "HasV9_1aOps", "true", "Support ARM v9.1a instructions",
846-
[HasV8_6aOps, HasV9_0aOps]>;
847-
848-
def HasV9_2aOps : SubtargetFeature<
849-
"v9.2a", "HasV9_2aOps", "true", "Support ARM v9.2a instructions",
850-
[HasV8_7aOps, HasV9_1aOps]>;
851-
852-
def HasV9_3aOps : SubtargetFeature<
853-
"v9.3a", "HasV9_3aOps", "true", "Support ARM v9.3a instructions",
854-
[HasV8_8aOps, HasV9_2aOps]>;
855-
856-
def HasV9_4aOps : SubtargetFeature<
857-
"v9.4a", "HasV9_4aOps", "true", "Support ARM v9.4a instructions",
858-
[HasV8_9aOps, HasV9_3aOps]>;
859-
860-
def HasV9_5aOps : SubtargetFeature<
861-
"v9.5a", "HasV9_5aOps", "true", "Support ARM v9.5a instructions",
862-
[HasV9_4aOps, FeatureCPA]>;
863-
864-
def HasV8_0rOps : SubtargetFeature<
865-
"v8r", "HasV8_0rOps", "true", "Support ARM v8r instructions",
866-
[//v8.1
867-
FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2,
868-
//v8.2
869-
FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV,
870-
//v8.3
871-
FeatureCCIDX, FeaturePAuth, FeatureRCPC,
872-
//v8.4
873-
FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2,
874-
FeatureRCPC_IMMO,
875-
// Not mandatory in v8.0-R, but included here on the grounds that it
876-
// only enables names of system registers
877-
FeatureSpecRestrict
878-
]>;
850+
FeatureCSSC, FeatureRASv2, FeatureCHK],
851+
!listconcat(HasV8_8aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC,
852+
FeatureRASv2])>;
853+
def HasV9_0aOps : Architecture64<9, 0, "a", "v9a",
854+
[HasV8_5aOps, FeatureMEC, FeatureSVE2],
855+
!listconcat(HasV8_5aOps.DefaultExts, [FeatureFullFP16, FeatureSVE,
856+
FeatureSVE2])>;
857+
def HasV9_1aOps : Architecture64<9, 1, "a", "v9.1a",
858+
[HasV8_6aOps, HasV9_0aOps],
859+
!listconcat(HasV9_0aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>;
860+
def HasV9_2aOps : Architecture64<9, 2, "a", "v9.2a",
861+
[HasV8_7aOps, HasV9_1aOps],
862+
!listconcat(HasV9_1aOps.DefaultExts, [])>;
863+
def HasV9_3aOps : Architecture64<9, 3, "a", "v9.3a",
864+
[HasV8_8aOps, HasV9_2aOps],
865+
!listconcat(HasV9_2aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>;
866+
def HasV9_4aOps : Architecture64<9, 4, "a", "v9.4a",
867+
[HasV8_9aOps, HasV9_3aOps],
868+
!listconcat(HasV9_3aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC,
869+
FeatureRASv2])>;
870+
def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a",
871+
[HasV9_4aOps, FeatureCPA],
872+
!listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA])>;
873+
def HasV8_0rOps : Architecture64<8, 0, "r", "v8r",
874+
[ //v8.1
875+
FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2,
876+
//v8.2
877+
FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV,
878+
//v8.3
879+
FeatureCCIDX, FeaturePAuth, FeatureRCPC,
880+
//v8.4
881+
FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2,
882+
FeatureRCPC_IMMO,
883+
// Not mandatory in v8.0-R, but included here on the grounds that it
884+
// only enables names of system registers
885+
FeatureSpecRestrict
886+
],
887+
// For v8-R, we do not enable crypto and align with GCC that enables a more
888+
// minimal set of optional architecture extensions.
889+
!listconcat(
890+
!listremove(HasV8_5aOps.DefaultExts, [FeatureLSE]),
891+
[FeatureSSBS, FeatureFullFP16, FeatureFP16FML, FeatureSB]
892+
)>;
879893

880894
//===----------------------------------------------------------------------===//
881895
// Access to privileged registers

llvm/utils/TableGen/ARMTargetDefEmitter.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "llvm/ADT/StringSet.h"
16+
#include "llvm/Support/Format.h"
17+
#include "llvm/TableGen/Error.h"
1618
#include "llvm/TableGen/Record.h"
1719
#include "llvm/TableGen/TableGenBackend.h"
1820
#include <cstdint>
21+
#include <string>
1922

2023
using namespace llvm;
2124

@@ -112,6 +115,68 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) {
112115
<< "#undef EMIT_EXTENSIONS\n"
113116
<< "#endif // EMIT_EXTENSIONS\n"
114117
<< "\n";
118+
119+
// Emit architecture information
120+
OS << "#ifdef EMIT_ARCHITECTURES\n";
121+
122+
auto Architectures = RK.getAllDerivedDefinitionsIfDefined("Architecture64");
123+
std::vector<std::string> CppSpellings;
124+
for (const Record *Rec : Architectures) {
125+
const int Major = Rec->getValueAsInt("Major");
126+
const int Minor = Rec->getValueAsInt("Minor");
127+
const std::string ProfileLower = Rec->getValueAsString("Profile").str();
128+
const std::string ProfileUpper = Rec->getValueAsString("Profile").upper();
129+
130+
if (ProfileLower != "a" && ProfileLower != "r")
131+
PrintFatalError(Rec->getLoc(),
132+
"error: Profile must be one of 'a' or 'r', got '" +
133+
ProfileLower + "'");
134+
135+
// Name of the object in C++
136+
const std::string CppSpelling =
137+
Minor == 0 ? "ARMV" + std::to_string(Major) + ProfileUpper.c_str()
138+
: "ARMV" + std::to_string(Major) + "_" +
139+
std::to_string(Minor) + ProfileUpper.c_str();
140+
OS << "inline constexpr ArchInfo " << CppSpelling << " = {\n";
141+
CppSpellings.push_back(CppSpelling);
142+
143+
OS << llvm::format(" VersionTuple{%d, %d},\n", Major, Minor);
144+
OS << llvm::format(" %sProfile,\n", ProfileUpper.c_str());
145+
146+
// Name as spelled for -march.
147+
if (Minor == 0)
148+
OS << llvm::format(" \"armv%d-%s\",\n", Major, ProfileLower.c_str());
149+
else
150+
OS << llvm::format(" \"armv%d.%d-%s\",\n", Major, Minor,
151+
ProfileLower.c_str());
152+
153+
// SubtargetFeature::Name, used for -target-feature. Here the "+" is added.
154+
const auto TargetFeatureName = Rec->getValueAsString("Name");
155+
OS << " \"+" << TargetFeatureName << "\",\n";
156+
157+
// Construct the list of default extensions
158+
OS << " (AArch64::ExtensionBitset({";
159+
for (auto *E : Rec->getValueAsListOfDefs("DefaultExts")) {
160+
// Only process subclasses of Extension
161+
OS << "AArch64::" << E->getValueAsString("ArchExtKindSpelling").upper()
162+
<< ", ";
163+
}
164+
OS << "}))\n";
165+
166+
OS << "};\n";
167+
}
168+
169+
OS << "\n"
170+
<< "/// The set of all architectures\n"
171+
<< "static constexpr std::array<const ArchInfo *, " << CppSpellings.size()
172+
<< "> ArchInfos = {\n";
173+
for (auto CppSpelling : CppSpellings)
174+
OS << " &" << CppSpelling << ",\n";
175+
OS << "};\n";
176+
177+
OS << "#undef EMIT_ARCHITECTURES\n"
178+
<< "#endif // EMIT_ARCHITECTURES\n"
179+
<< "\n";
115180
}
116181

117182
static TableGen::Emitter::Opt

0 commit comments

Comments
 (0)