1 //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a target parser to recognise AArch64 hardware features
10 // such as FPU/CPU/ARCH and extension names.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
15 #define LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/Bitset.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/VersionTuple.h"
22 #include <array>
23 #include <vector>
24 
25 namespace llvm {
26 
27 class Triple;
28 
29 namespace AArch64 {
30 
31 struct ArchInfo;
32 struct CpuInfo;
33 
34 // Function Multi Versioning CPU features. They must be kept in sync with
35 // compiler-rt enum CPUFeatures in lib/builtins/cpu_model/aarch64.c with
36 // FEAT_MAX as sentinel.
37 enum CPUFeatures {
38   FEAT_RNG,
39   FEAT_FLAGM,
40   FEAT_FLAGM2,
41   FEAT_FP16FML,
42   FEAT_DOTPROD,
43   FEAT_SM4,
44   FEAT_RDM,
45   FEAT_LSE,
46   FEAT_FP,
47   FEAT_SIMD,
48   FEAT_CRC,
49   FEAT_SHA1,
50   FEAT_SHA2,
51   FEAT_SHA3,
52   FEAT_AES,
53   FEAT_PMULL,
54   FEAT_FP16,
55   FEAT_DIT,
56   FEAT_DPB,
57   FEAT_DPB2,
58   FEAT_JSCVT,
59   FEAT_FCMA,
60   FEAT_RCPC,
61   FEAT_RCPC2,
62   FEAT_FRINTTS,
63   FEAT_DGH,
64   FEAT_I8MM,
65   FEAT_BF16,
66   FEAT_EBF16,
67   FEAT_RPRES,
68   FEAT_SVE,
69   FEAT_SVE_BF16,
70   FEAT_SVE_EBF16,
71   FEAT_SVE_I8MM,
72   FEAT_SVE_F32MM,
73   FEAT_SVE_F64MM,
74   FEAT_SVE2,
75   FEAT_SVE_AES,
76   FEAT_SVE_PMULL128,
77   FEAT_SVE_BITPERM,
78   FEAT_SVE_SHA3,
79   FEAT_SVE_SM4,
80   FEAT_SME,
81   FEAT_MEMTAG,
82   FEAT_MEMTAG2,
83   FEAT_MEMTAG3,
84   FEAT_SB,
85   FEAT_PREDRES,
86   FEAT_SSBS,
87   FEAT_SSBS2,
88   FEAT_BTI,
89   FEAT_LS64,
90   FEAT_LS64_V,
91   FEAT_LS64_ACCDATA,
92   FEAT_WFXT,
93   FEAT_SME_F64,
94   FEAT_SME_I64,
95   FEAT_SME2,
96   FEAT_RCPC3,
97   FEAT_MOPS,
98   FEAT_MAX,
99   FEAT_EXT = 62,
100   FEAT_INIT
101 };
102 
103 static_assert(FEAT_MAX < 62,
104               "Number of features in CPUFeatures are limited to 62 entries");
105 
106 // Each ArchExtKind correponds directly to a possible -target-feature.
107 #define EMIT_ARCHEXTKIND_ENUM
108 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
109 
110 using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
111 
112 // Represents an extension that can be enabled with -march=<arch>+<extension>.
113 // Typically these correspond to Arm Architecture extensions, unlike
114 // SubtargetFeature which may represent either an actual extension or some
115 // internal LLVM property.
116 struct ExtensionInfo {
117   StringRef Name;              // Human readable name, e.g. "profile".
118   ArchExtKind ID;              // Corresponding to the ArchExtKind, this
119                                // extensions representation in the bitfield.
120   StringRef Feature;           // -mattr enable string, e.g. "+spe"
121   StringRef NegFeature;        // -mattr disable string, e.g. "-spe"
122   CPUFeatures CPUFeature;      // Function Multi Versioning (FMV) bitfield value
123                                // set in __aarch64_cpu_features
124   StringRef DependentFeatures; // FMV enabled features string,
125                                // e.g. "+dotprod,+fp-armv8,+neon"
126   unsigned FmvPriority;        // FMV feature priority
127   static constexpr unsigned MaxFMVPriority =
128       1000; // Maximum priority for FMV feature
129 };
130 
131 #define EMIT_EXTENSIONS
132 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
133 
134 struct ExtensionSet {
135   // Set of extensions which are currently enabled.
136   ExtensionBitset Enabled;
137   // Set of extensions which have been enabled or disabled at any point. Used
138   // to avoid cluttering the cc1 command-line with lots of unneeded features.
139   ExtensionBitset Touched;
140   // Base architecture version, which we need to know because some feature
141   // dependencies change depending on this.
142   const ArchInfo *BaseArch;
143 
ExtensionSetExtensionSet144   ExtensionSet() : Enabled(), Touched(), BaseArch(nullptr) {}
145 
146   // Enable the given architecture extension, and any other extensions it
147   // depends on. Does not change the base architecture, or follow dependencies
148   // between features which are only related by required arcitecture versions.
149   void enable(ArchExtKind E);
150 
151   // Disable the given architecture extension, and any other extensions which
152   // depend on it. Does not change the base architecture, or follow
153   // dependencies between features which are only related by required
154   // arcitecture versions.
155   void disable(ArchExtKind E);
156 
157   // Add default extensions for the given CPU. Records the base architecture,
158   // to later resolve dependencies which depend on it.
159   void addCPUDefaults(const CpuInfo &CPU);
160 
161   // Add default extensions for the given architecture version. Records the
162   // base architecture, to later resolve dependencies which depend on it.
163   void addArchDefaults(const ArchInfo &Arch);
164 
165   // Add or remove a feature based on a modifier string. The string must be of
166   // the form "<name>" to enable a feature or "no<name>" to disable it. This
167   // will also enable or disable any features as required by the dependencies
168   // between them.
169   bool parseModifier(StringRef Modifier);
170 
171   // Convert the set of enabled extension to an LLVM feature list, appending
172   // them to Features.
173   void toLLVMFeatureList(std::vector<StringRef> &Features) const;
174 };
175 
176 // Represents a dependency between two architecture extensions. Later is the
177 // feature which was added to the architecture after Earlier, and expands the
178 // functionality provided by it. If Later is enabled, then Earlier will also be
179 // enabled. If Earlier is disabled, then Later will also be disabled.
180 struct ExtensionDependency {
181   ArchExtKind Earlier;
182   ArchExtKind Later;
183 };
184 
185 // clang-format off
186 // Each entry here is a link in the dependency chain starting from the
187 // extension that was added to the architecture first.
188 inline constexpr ExtensionDependency ExtensionDependencies[] = {
189   {AEK_FP, AEK_FP16},
190   {AEK_FP, AEK_SIMD},
191   {AEK_FP, AEK_JSCVT},
192   {AEK_FP, AEK_FP8},
193   {AEK_SIMD, AEK_CRYPTO},
194   {AEK_SIMD, AEK_AES},
195   {AEK_SIMD, AEK_SHA2},
196   {AEK_SIMD, AEK_SHA3},
197   {AEK_SIMD, AEK_SM4},
198   {AEK_SIMD, AEK_RDM},
199   {AEK_SIMD, AEK_DOTPROD},
200   {AEK_SIMD, AEK_FCMA},
201   {AEK_FP16, AEK_FP16FML},
202   {AEK_FP16, AEK_SVE},
203   {AEK_BF16, AEK_SME},
204   {AEK_BF16, AEK_B16B16},
205   {AEK_SVE, AEK_SVE2},
206   {AEK_SVE, AEK_F32MM},
207   {AEK_SVE, AEK_F64MM},
208   {AEK_SVE2, AEK_SVE2P1},
209   {AEK_SVE2, AEK_SVE2BITPERM},
210   {AEK_SVE2, AEK_SVE2AES},
211   {AEK_SVE2, AEK_SVE2SHA3},
212   {AEK_SVE2, AEK_SVE2SM4},
213   {AEK_SVE2, AEK_SMEFA64},
214   {AEK_SVE2, AEK_SMEFA64},
215   {AEK_SME, AEK_SME2},
216   {AEK_SME, AEK_SMEF16F16},
217   {AEK_SME, AEK_SMEF64F64},
218   {AEK_SME, AEK_SMEI16I64},
219   {AEK_SME, AEK_SMEFA64},
220   {AEK_SME2, AEK_SME2P1},
221   {AEK_SME2, AEK_SSVE_FP8FMA},
222   {AEK_SME2, AEK_SSVE_FP8DOT2},
223   {AEK_SME2, AEK_SSVE_FP8DOT4},
224   {AEK_SME2, AEK_SMEF8F16},
225   {AEK_SME2, AEK_SMEF8F32},
226   {AEK_FP8, AEK_SMEF8F16},
227   {AEK_FP8, AEK_SMEF8F32},
228   {AEK_LSE, AEK_LSE128},
229   {AEK_PREDRES, AEK_SPECRES2},
230   {AEK_RAS, AEK_RASV2},
231   {AEK_RCPC, AEK_RCPC3},
232 };
233 // clang-format on
234 
235 enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
236 
237 // Information about a specific architecture, e.g. V8.1-A
238 struct ArchInfo {
239   VersionTuple Version;  // Architecture version, major + minor.
240   ArchProfile Profile;   // Architecuture profile
241   StringRef Name;        // Human readable name, e.g. "armv8.1-a"
242   StringRef ArchFeature; // Command line feature flag, e.g. +v8a
243   AArch64::ExtensionBitset
244       DefaultExts; // bitfield of default extensions ArchExtKind
245 
246   bool operator==(const ArchInfo &Other) const {
247     return this->Name == Other.Name;
248   }
249   bool operator!=(const ArchInfo &Other) const {
250     return this->Name != Other.Name;
251   }
252 
253   // Defines the following partial order, indicating when an architecture is
254   // a superset of another:
255   //
256   //   v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a;
257   //             v       v       v       v       v
258   //           v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
259   //
260   // v8r has no relation to anything. This is used to determine which
261   // features to enable for a given architecture. See
262   // AArch64TargetInfo::setFeatureEnabled.
impliesArchInfo263   bool implies(const ArchInfo &Other) const {
264     if (this->Profile != Other.Profile)
265       return false; // ARMV8R
266     if (this->Version.getMajor() == Other.Version.getMajor()) {
267       return this->Version > Other.Version;
268     }
269     if (this->Version.getMajor() == 9 && Other.Version.getMajor() == 8) {
270       assert(this->Version.getMinor() && Other.Version.getMinor() &&
271              "AArch64::ArchInfo should have a minor version.");
272       return this->Version.getMinor().value_or(0) + 5 >=
273              Other.Version.getMinor().value_or(0);
274     }
275     return false;
276   }
277 
278   // True if this architecture is a superset of Other (including being equal to
279   // it).
is_supersetArchInfo280   bool is_superset(const ArchInfo &Other) const {
281     return (*this == Other) || implies(Other);
282   }
283 
284   // Return ArchFeature without the leading "+".
getSubArchArchInfo285   StringRef getSubArch() const { return ArchFeature.substr(1); }
286 
287   // Search for ArchInfo by SubArch name
288   static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
289 };
290 
291 // clang-format off
292 inline constexpr ArchInfo ARMV8A    = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", (
293                                         AArch64::ExtensionBitset({AArch64::AEK_FP, AArch64::AEK_SIMD})), };
294 inline constexpr ArchInfo ARMV8_1A  = { VersionTuple{8, 1}, AProfile, "armv8.1-a", "+v8.1a", (ARMV8A.DefaultExts |
295                                         AArch64::ExtensionBitset({AArch64::AEK_CRC, AArch64::AEK_LSE, AArch64::AEK_RDM}))};
296 inline constexpr ArchInfo ARMV8_2A  = { VersionTuple{8, 2}, AProfile, "armv8.2-a", "+v8.2a", (ARMV8_1A.DefaultExts |
297                                         AArch64::ExtensionBitset({AArch64::AEK_RAS}))};
298 inline constexpr ArchInfo ARMV8_3A  = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts |
299                                         AArch64::ExtensionBitset({AArch64::AEK_FCMA, AArch64::AEK_JSCVT, AArch64::AEK_PAUTH, AArch64::AEK_RCPC}))};
300 inline constexpr ArchInfo ARMV8_4A  = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts |
301                                         AArch64::ExtensionBitset({AArch64::AEK_DOTPROD}))};
302 inline constexpr ArchInfo ARMV8_5A  = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)};
303 inline constexpr ArchInfo ARMV8_6A  = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts |
304                                         AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))};
305 inline constexpr ArchInfo ARMV8_7A  = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)};
306 inline constexpr ArchInfo ARMV8_8A  = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts |
307                                         AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))};
308 inline constexpr ArchInfo ARMV8_9A  = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts |
309                                         AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))};
310 inline constexpr ArchInfo ARMV9A    = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts |
311                                         AArch64::ExtensionBitset({AArch64::AEK_FP16, AArch64::AEK_SVE, AArch64::AEK_SVE2}))};
312 inline constexpr ArchInfo ARMV9_1A  = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts |
313                                         AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))};
314 inline constexpr ArchInfo ARMV9_2A  = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)};
315 inline constexpr ArchInfo ARMV9_3A  = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts |
316                                         AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))};
317 inline constexpr ArchInfo ARMV9_4A  = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts |
318                                         AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))};
319 inline constexpr ArchInfo ARMV9_5A  = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts |
320                                         AArch64::ExtensionBitset({AArch64::AEK_CPA}))};
321 // For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions.
322 inline constexpr ArchInfo ARMV8R    = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", (ARMV8_5A.DefaultExts |
323                                         AArch64::ExtensionBitset({AArch64::AEK_SSBS,
324                                         AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_SB}).flip(AArch64::AEK_LSE))};
325 // clang-format on
326 
327 // The set of all architectures
328 static constexpr std::array<const ArchInfo *, 17> ArchInfos = {
329     &ARMV8A,   &ARMV8_1A, &ARMV8_2A, &ARMV8_3A, &ARMV8_4A, &ARMV8_5A,
330     &ARMV8_6A, &ARMV8_7A, &ARMV8_8A, &ARMV8_9A, &ARMV9A,   &ARMV9_1A,
331     &ARMV9_2A, &ARMV9_3A, &ARMV9_4A, &ARMV9_5A, &ARMV8R,
332 };
333 
334 // Details of a specific CPU.
335 struct CpuInfo {
336   StringRef Name; // Name, as written for -mcpu.
337   const ArchInfo &Arch;
338   AArch64::ExtensionBitset
339       DefaultExtensions; // Default extensions for this CPU. These will be
340                          // ORd with the architecture defaults.
341 
getImpliedExtensionsCpuInfo342   AArch64::ExtensionBitset getImpliedExtensions() const {
343     AArch64::ExtensionBitset ImpliedExts;
344     ImpliedExts |= DefaultExtensions;
345     ImpliedExts |= Arch.DefaultExts;
346     return ImpliedExts;
347   }
348 };
349 
350 inline constexpr CpuInfo CpuInfos[] = {
351     {"cortex-a34", ARMV8A,
352      AArch64::ExtensionBitset(
353          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
354     {"cortex-a35", ARMV8A,
355      AArch64::ExtensionBitset(
356          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
357     {"cortex-a53", ARMV8A,
358      AArch64::ExtensionBitset(
359          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
360     {"cortex-a55", ARMV8_2A,
361      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
362                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
363                                AArch64::AEK_RCPC})},
364     {"cortex-a510", ARMV9A,
365      AArch64::ExtensionBitset(
366          {AArch64::AEK_BF16, AArch64::AEK_I8MM, AArch64::AEK_SB,
367           AArch64::AEK_PAUTH, AArch64::AEK_MTE, AArch64::AEK_SSBS,
368           AArch64::AEK_SVE, AArch64::AEK_SVE2, AArch64::AEK_SVE2BITPERM,
369           AArch64::AEK_FP16FML})},
370     {"cortex-a520", ARMV9_2A,
371      AArch64::ExtensionBitset(
372          {AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
373           AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
374           AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
375     {"cortex-a520ae", ARMV9_2A,
376      AArch64::ExtensionBitset(
377          {AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
378           AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
379           AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
380     {"cortex-a57", ARMV8A,
381      AArch64::ExtensionBitset(
382          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
383     {"cortex-a65", ARMV8_2A,
384      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
385                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
386                                AArch64::AEK_RCPC, AArch64::AEK_SSBS})},
387     {"cortex-a65ae", ARMV8_2A,
388      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
389                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
390                                AArch64::AEK_RCPC, AArch64::AEK_SSBS})},
391     {"cortex-a72", ARMV8A,
392      AArch64::ExtensionBitset(
393          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
394     {"cortex-a73", ARMV8A,
395      AArch64::ExtensionBitset(
396          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
397     {"cortex-a75", ARMV8_2A,
398      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
399                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
400                                AArch64::AEK_RCPC})},
401     {"cortex-a76", ARMV8_2A,
402      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
403                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
404                                AArch64::AEK_RCPC, AArch64::AEK_SSBS})},
405     {"cortex-a76ae", ARMV8_2A,
406      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
407                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
408                                AArch64::AEK_RCPC, AArch64::AEK_SSBS})},
409     {"cortex-a77", ARMV8_2A,
410      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
411                                AArch64::AEK_FP16, AArch64::AEK_RCPC,
412                                AArch64::AEK_DOTPROD, AArch64::AEK_SSBS})},
413     {"cortex-a78", ARMV8_2A,
414      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
415                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
416                                AArch64::AEK_RCPC, AArch64::AEK_SSBS,
417                                AArch64::AEK_PROFILE})},
418     {"cortex-a78ae", ARMV8_2A,
419      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
420                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
421                                AArch64::AEK_RCPC, AArch64::AEK_SSBS,
422                                AArch64::AEK_PROFILE})},
423     {"cortex-a78c", ARMV8_2A,
424      AArch64::ExtensionBitset(
425          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16,
426           AArch64::AEK_DOTPROD, AArch64::AEK_RCPC, AArch64::AEK_SSBS,
427           AArch64::AEK_PROFILE, AArch64::AEK_FLAGM, AArch64::AEK_PAUTH})},
428     {"cortex-a710", ARMV9A,
429      AArch64::ExtensionBitset({AArch64::AEK_MTE, AArch64::AEK_PAUTH,
430                                AArch64::AEK_FLAGM, AArch64::AEK_SB,
431                                AArch64::AEK_I8MM, AArch64::AEK_FP16FML,
432                                AArch64::AEK_SVE, AArch64::AEK_SVE2,
433                                AArch64::AEK_SVE2BITPERM, AArch64::AEK_BF16})},
434     {"cortex-a715", ARMV9A,
435      AArch64::ExtensionBitset(
436          {AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
437           AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_PAUTH,
438           AArch64::AEK_I8MM, AArch64::AEK_PREDRES, AArch64::AEK_PERFMON,
439           AArch64::AEK_PROFILE, AArch64::AEK_SVE, AArch64::AEK_SVE2BITPERM,
440           AArch64::AEK_BF16, AArch64::AEK_FLAGM})},
441     {"cortex-a720", ARMV9_2A,
442      AArch64::ExtensionBitset({AArch64::AEK_SB, AArch64::AEK_SSBS,
443                                AArch64::AEK_MTE, AArch64::AEK_FP16FML,
444                                AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
445                                AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
446                                AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})},
447     {"cortex-a720ae", ARMV9_2A,
448      AArch64::ExtensionBitset({AArch64::AEK_SB, AArch64::AEK_SSBS,
449                                AArch64::AEK_MTE, AArch64::AEK_FP16FML,
450                                AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
451                                AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
452                                AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})},
453     {"cortex-r82", ARMV8R,
454      AArch64::ExtensionBitset({AArch64::AEK_LSE, AArch64::AEK_FLAGM,
455                                AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
456     {"cortex-r82ae", ARMV8R,
457      AArch64::ExtensionBitset({AArch64::AEK_LSE, AArch64::AEK_FLAGM,
458                                AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
459     {"cortex-x1", ARMV8_2A,
460      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
461                                AArch64::AEK_FP16, AArch64::AEK_DOTPROD,
462                                AArch64::AEK_RCPC, AArch64::AEK_SSBS,
463                                AArch64::AEK_PROFILE})},
464     {"cortex-x1c", ARMV8_2A,
465      AArch64::ExtensionBitset(
466          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16,
467           AArch64::AEK_DOTPROD, AArch64::AEK_RCPC, AArch64::AEK_SSBS,
468           AArch64::AEK_PAUTH, AArch64::AEK_PROFILE, AArch64::AEK_FLAGM})},
469     {"cortex-x2", ARMV9A,
470      AArch64::ExtensionBitset(
471          {AArch64::AEK_MTE, AArch64::AEK_BF16, AArch64::AEK_I8MM,
472           AArch64::AEK_PAUTH, AArch64::AEK_SSBS, AArch64::AEK_SB,
473           AArch64::AEK_SVE, AArch64::AEK_SVE2, AArch64::AEK_SVE2BITPERM,
474           AArch64::AEK_FP16FML, AArch64::AEK_FLAGM})},
475     {"cortex-x3", ARMV9A,
476      AArch64::ExtensionBitset(
477          {AArch64::AEK_SVE, AArch64::AEK_PERFMON, AArch64::AEK_PROFILE,
478           AArch64::AEK_BF16, AArch64::AEK_I8MM, AArch64::AEK_MTE,
479           AArch64::AEK_SVE2BITPERM, AArch64::AEK_SB, AArch64::AEK_PAUTH,
480           AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_PREDRES,
481           AArch64::AEK_FLAGM, AArch64::AEK_SSBS})},
482     {"cortex-x4", ARMV9_2A,
483      AArch64::ExtensionBitset({AArch64::AEK_SB, AArch64::AEK_SSBS,
484                                AArch64::AEK_MTE, AArch64::AEK_FP16FML,
485                                AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
486                                AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
487                                AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})},
488     {"neoverse-e1", ARMV8_2A,
489      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
490                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
491                                AArch64::AEK_RCPC, AArch64::AEK_SSBS})},
492     {"neoverse-n1", ARMV8_2A,
493      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
494                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
495                                AArch64::AEK_PROFILE, AArch64::AEK_RCPC,
496                                AArch64::AEK_SSBS})},
497     {"neoverse-n2", ARMV9A,
498      AArch64::ExtensionBitset(
499          {AArch64::AEK_BF16, AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
500           AArch64::AEK_FP16FML, AArch64::AEK_I8MM, AArch64::AEK_MTE,
501           AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_SVE,
502           AArch64::AEK_SVE2, AArch64::AEK_SVE2BITPERM})},
503     {"neoverse-n3", ARMV9_2A,
504      AArch64::ExtensionBitset({AArch64::AEK_MTE, AArch64::AEK_SSBS,
505                                AArch64::AEK_SB, AArch64::AEK_PREDRES,
506                                AArch64::AEK_FP16FML, AArch64::AEK_PAUTH,
507                                AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
508                                AArch64::AEK_RAND, AArch64::AEK_SVE2BITPERM,
509                                AArch64::AEK_PROFILE, AArch64::AEK_PERFMON})},
510     {"neoverse-512tvb", ARMV8_4A,
511      AArch64::ExtensionBitset(
512          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_SHA3,
513           AArch64::AEK_SM4, AArch64::AEK_SVE, AArch64::AEK_SSBS,
514           AArch64::AEK_FP16, AArch64::AEK_BF16, AArch64::AEK_DOTPROD,
515           AArch64::AEK_PROFILE, AArch64::AEK_RAND, AArch64::AEK_FP16FML,
516           AArch64::AEK_I8MM})},
517     {"neoverse-v1", ARMV8_4A,
518      AArch64::ExtensionBitset(
519          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_SHA3,
520           AArch64::AEK_SM4, AArch64::AEK_SVE, AArch64::AEK_SSBS,
521           AArch64::AEK_FP16, AArch64::AEK_BF16, AArch64::AEK_DOTPROD,
522           AArch64::AEK_PROFILE, AArch64::AEK_RAND, AArch64::AEK_FP16FML,
523           AArch64::AEK_I8MM})},
524     {"neoverse-v2", ARMV9A,
525      AArch64::ExtensionBitset(
526          {AArch64::AEK_SVE, AArch64::AEK_SVE2, AArch64::AEK_SSBS,
527           AArch64::AEK_FP16, AArch64::AEK_BF16, AArch64::AEK_RAND,
528           AArch64::AEK_DOTPROD, AArch64::AEK_PROFILE, AArch64::AEK_SVE2BITPERM,
529           AArch64::AEK_FP16FML, AArch64::AEK_I8MM, AArch64::AEK_MTE})},
530     {"neoverse-v3", ARMV9_2A,
531      AArch64::ExtensionBitset(
532          {AArch64::AEK_PROFILE, AArch64::AEK_MTE, AArch64::AEK_SSBS,
533           AArch64::AEK_SB, AArch64::AEK_PREDRES, AArch64::AEK_LS64,
534           AArch64::AEK_BRBE, AArch64::AEK_PAUTH, AArch64::AEK_FLAGM,
535           AArch64::AEK_PERFMON, AArch64::AEK_RAND, AArch64::AEK_SVE2BITPERM,
536           AArch64::AEK_FP16FML})},
537     {"neoverse-v3ae", ARMV9_2A,
538      (AArch64::ExtensionBitset(
539          {AArch64::AEK_PROFILE, AArch64::AEK_MTE, AArch64::AEK_SSBS,
540           AArch64::AEK_SB, AArch64::AEK_PREDRES, AArch64::AEK_LS64,
541           AArch64::AEK_BRBE, AArch64::AEK_PAUTH, AArch64::AEK_FLAGM,
542           AArch64::AEK_PERFMON, AArch64::AEK_RAND, AArch64::AEK_SVE2BITPERM,
543           AArch64::AEK_FP16FML}))},
544     {"cyclone", ARMV8A,
545      AArch64::ExtensionBitset(
546          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_NONE})},
547     {"apple-a7", ARMV8A,
548      AArch64::ExtensionBitset(
549          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_NONE})},
550     {"apple-a8", ARMV8A,
551      AArch64::ExtensionBitset(
552          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_NONE})},
553     {"apple-a9", ARMV8A,
554      AArch64::ExtensionBitset(
555          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_NONE})},
556     {"apple-a10", ARMV8A,
557      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
558                                AArch64::AEK_CRC, AArch64::AEK_RDM})},
559     {"apple-a11", ARMV8_2A,
560      AArch64::ExtensionBitset(
561          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16})},
562     {"apple-a12", ARMV8_3A,
563      AArch64::ExtensionBitset(
564          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16})},
565     {"apple-a13", ARMV8_4A,
566      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
567                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
568                                AArch64::AEK_FP16FML})},
569     {"apple-a14", ARMV8_5A,
570      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
571                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
572                                AArch64::AEK_FP16FML})},
573     {"apple-a15", ARMV8_6A,
574      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
575                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
576                                AArch64::AEK_FP16FML})},
577     {"apple-a16", ARMV8_6A,
578      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
579                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
580                                AArch64::AEK_FP16FML})},
581     {"apple-a17", ARMV8_6A,
582      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
583                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
584                                AArch64::AEK_FP16FML})},
585 
586     {"apple-m1", ARMV8_5A,
587      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
588                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
589                                AArch64::AEK_FP16FML})},
590     {"apple-m2", ARMV8_6A,
591      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
592                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
593                                AArch64::AEK_FP16FML})},
594     {"apple-m3", ARMV8_6A,
595      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
596                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
597                                AArch64::AEK_FP16FML})},
598 
599     {"apple-s4", ARMV8_3A,
600      AArch64::ExtensionBitset(
601          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16})},
602     {"apple-s5", ARMV8_3A,
603      AArch64::ExtensionBitset(
604          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16})},
605     {"exynos-m3", ARMV8A,
606      AArch64::ExtensionBitset(
607          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
608     {"exynos-m4", ARMV8_2A,
609      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
610                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16})},
611     {"exynos-m5", ARMV8_2A,
612      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
613                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16})},
614     {"falkor", ARMV8A,
615      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
616                                AArch64::AEK_CRC, AArch64::AEK_RDM})},
617     {"saphira", ARMV8_3A,
618      AArch64::ExtensionBitset(
619          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_PROFILE})},
620     {"kryo", ARMV8A,
621      AArch64::ExtensionBitset(
622          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
623     {"thunderx2t99", ARMV8_1A,
624      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2})},
625     {"thunderx3t110", ARMV8_3A,
626      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2})},
627     {"thunderx", ARMV8A,
628      AArch64::ExtensionBitset(
629          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
630     {"thunderxt88", ARMV8A,
631      AArch64::ExtensionBitset(
632          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
633     {"thunderxt81", ARMV8A,
634      AArch64::ExtensionBitset(
635          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
636     {"thunderxt83", ARMV8A,
637      AArch64::ExtensionBitset(
638          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
639     {"tsv110", ARMV8_2A,
640      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
641                                AArch64::AEK_DOTPROD, AArch64::AEK_FP16,
642                                AArch64::AEK_FP16FML, AArch64::AEK_PROFILE,
643                                AArch64::AEK_JSCVT, AArch64::AEK_FCMA})},
644     {"a64fx", ARMV8_2A,
645      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
646                                AArch64::AEK_FP16, AArch64::AEK_SVE})},
647     {"carmel", ARMV8_2A,
648      AArch64::ExtensionBitset(
649          {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_FP16})},
650     {"ampere1", ARMV8_6A,
651      AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
652                                AArch64::AEK_SHA3, AArch64::AEK_FP16,
653                                AArch64::AEK_SB, AArch64::AEK_SSBS,
654                                AArch64::AEK_RAND})},
655     {"ampere1a", ARMV8_6A,
656      AArch64::ExtensionBitset(
657          {AArch64::AEK_FP16, AArch64::AEK_RAND, AArch64::AEK_SM4,
658           AArch64::AEK_SHA3, AArch64::AEK_SHA2, AArch64::AEK_AES,
659           AArch64::AEK_MTE, AArch64::AEK_SB, AArch64::AEK_SSBS})},
660     {"ampere1b", ARMV8_7A,
661      AArch64::ExtensionBitset({AArch64::AEK_FP16, AArch64::AEK_RAND,
662                                AArch64::AEK_SM4, AArch64::AEK_SHA3,
663                                AArch64::AEK_SHA2, AArch64::AEK_AES,
664                                AArch64::AEK_MTE, AArch64::AEK_SB,
665                                AArch64::AEK_SSBS, AArch64::AEK_CSSC})},
666 };
667 
668 // Name alias.
669 struct Alias {
670   StringRef AltName;
671   StringRef Name;
672 };
673 
674 inline constexpr Alias CpuAliases[] = {{"cobalt-100", "neoverse-n2"},
675                                        {"grace", "neoverse-v2"}};
676 
677 inline constexpr Alias ExtAliases[] = {{"rdma", "rdm"}};
678 
679 const ExtensionInfo &getExtensionByID(ArchExtKind(ExtID));
680 
681 bool getExtensionFeatures(
682     const AArch64::ExtensionBitset &Extensions,
683     std::vector<StringRef> &Features);
684 
685 StringRef getArchExtFeature(StringRef ArchExt);
686 StringRef resolveCPUAlias(StringRef CPU);
687 StringRef resolveExtAlias(StringRef ArchExt);
688 
689 // Information by Name
690 const ArchInfo *getArchForCpu(StringRef CPU);
691 
692 // Parser
693 const ArchInfo *parseArch(StringRef Arch);
694 std::optional<ExtensionInfo> parseArchExtension(StringRef Extension);
695 // Given the name of a CPU or alias, return the correponding CpuInfo.
696 std::optional<CpuInfo> parseCpu(StringRef Name);
697 // Used by target parser tests
698 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
699 
700 bool isX18ReservedByDefault(const Triple &TT);
701 
702 // For given feature names, return a bitmask corresponding to the entries of
703 // AArch64::CPUFeatures. The values in CPUFeatures are not bitmasks
704 // themselves, they are sequential (0, 1, 2, 3, ...).
705 uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
706 
707 void PrintSupportedExtensions(StringMap<StringRef> DescMap);
708 
709 } // namespace AArch64
710 } // namespace llvm
711 
712 #endif
713