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/StringRef.h"
19 #include "llvm/Support/VersionTuple.h"
20 #include <array>
21 #include <vector>
22 
23 namespace llvm {
24 
25 class Triple;
26 
27 namespace AArch64 {
28 // Function Multi Versioning CPU features. They must be kept in sync with
29 // compiler-rt enum CPUFeatures in lib/builtins/cpu_model.c with FEAT_MAX as
30 // sentinel.
31 enum CPUFeatures {
32   FEAT_RNG,
33   FEAT_FLAGM,
34   FEAT_FLAGM2,
35   FEAT_FP16FML,
36   FEAT_DOTPROD,
37   FEAT_SM4,
38   FEAT_RDM,
39   FEAT_LSE,
40   FEAT_FP,
41   FEAT_SIMD,
42   FEAT_CRC,
43   FEAT_SHA1,
44   FEAT_SHA2,
45   FEAT_SHA3,
46   FEAT_AES,
47   FEAT_PMULL,
48   FEAT_FP16,
49   FEAT_DIT,
50   FEAT_DPB,
51   FEAT_DPB2,
52   FEAT_JSCVT,
53   FEAT_FCMA,
54   FEAT_RCPC,
55   FEAT_RCPC2,
56   FEAT_FRINTTS,
57   FEAT_DGH,
58   FEAT_I8MM,
59   FEAT_BF16,
60   FEAT_EBF16,
61   FEAT_RPRES,
62   FEAT_SVE,
63   FEAT_SVE_BF16,
64   FEAT_SVE_EBF16,
65   FEAT_SVE_I8MM,
66   FEAT_SVE_F32MM,
67   FEAT_SVE_F64MM,
68   FEAT_SVE2,
69   FEAT_SVE_AES,
70   FEAT_SVE_PMULL128,
71   FEAT_SVE_BITPERM,
72   FEAT_SVE_SHA3,
73   FEAT_SVE_SM4,
74   FEAT_SME,
75   FEAT_MEMTAG,
76   FEAT_MEMTAG2,
77   FEAT_MEMTAG3,
78   FEAT_SB,
79   FEAT_PREDRES,
80   FEAT_SSBS,
81   FEAT_SSBS2,
82   FEAT_BTI,
83   FEAT_LS64,
84   FEAT_LS64_V,
85   FEAT_LS64_ACCDATA,
86   FEAT_WFXT,
87   FEAT_SME_F64,
88   FEAT_SME_I64,
89   FEAT_SME2,
90   FEAT_MAX
91 };
92 
93 static_assert(FEAT_MAX <= 64,
94               "CPUFeatures enum must not have more than 64 entries");
95 
96 // Arch extension modifiers for CPUs. These are labelled with their Arm ARM
97 // feature name (though the canonical reference for those is AArch64.td)
98 // clang-format off
99 enum ArchExtKind : uint64_t {
100   AEK_NONE =        1,
101   AEK_CRC =         1 << 1,  // FEAT_CRC32
102   AEK_CRYPTO =      1 << 2,
103   AEK_FP =          1 << 3,  // FEAT_FP
104   AEK_SIMD =        1 << 4,  // FEAT_AdvSIMD
105   AEK_FP16 =        1 << 5,  // FEAT_FP16
106   AEK_PROFILE =     1 << 6,  // FEAT_SPE
107   AEK_RAS =         1 << 7,  // FEAT_RAS, FEAT_RASv1p1
108   AEK_LSE =         1 << 8,  // FEAT_LSE
109   AEK_SVE =         1 << 9,  // FEAT_SVE
110   AEK_DOTPROD =     1 << 10, // FEAT_DotProd
111   AEK_RCPC =        1 << 11, // FEAT_LRCPC
112   AEK_RDM =         1 << 12, // FEAT_RDM
113   AEK_SM4 =         1 << 13, // FEAT_SM4, FEAT_SM3
114   AEK_SHA3 =        1 << 14, // FEAT_SHA3, FEAT_SHA512
115   AEK_SHA2 =        1 << 15, // FEAT_SHA1, FEAT_SHA256
116   AEK_AES =         1 << 16, // FEAT_AES, FEAT_PMULL
117   AEK_FP16FML =     1 << 17, // FEAT_FHM
118   AEK_RAND =        1 << 18, // FEAT_RNG
119   AEK_MTE =         1 << 19, // FEAT_MTE, FEAT_MTE2
120   AEK_SSBS =        1 << 20, // FEAT_SSBS, FEAT_SSBS2
121   AEK_SB =          1 << 21, // FEAT_SB
122   AEK_PREDRES =     1 << 22, // FEAT_SPECRES
123   AEK_SVE2 =        1 << 23, // FEAT_SVE2
124   AEK_SVE2AES =     1 << 24, // FEAT_SVE_AES, FEAT_SVE_PMULL128
125   AEK_SVE2SM4 =     1 << 25, // FEAT_SVE_SM4
126   AEK_SVE2SHA3 =    1 << 26, // FEAT_SVE_SHA3
127   AEK_SVE2BITPERM = 1 << 27, // FEAT_SVE_BitPerm
128   AEK_TME =         1 << 28, // FEAT_TME
129   AEK_BF16 =        1 << 29, // FEAT_BF16
130   AEK_I8MM =        1 << 30, // FEAT_I8MM
131   AEK_F32MM =       1ULL << 31, // FEAT_F32MM
132   AEK_F64MM =       1ULL << 32, // FEAT_F64MM
133   AEK_LS64 =        1ULL << 33, // FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA
134   AEK_BRBE =        1ULL << 34, // FEAT_BRBE
135   AEK_PAUTH =       1ULL << 35, // FEAT_PAuth
136   AEK_FLAGM =       1ULL << 36, // FEAT_FlagM
137   AEK_SME =         1ULL << 37, // FEAT_SME
138   AEK_SMEF64F64 =   1ULL << 38, // FEAT_SME_F64F64
139   AEK_SMEI16I64 =   1ULL << 39, // FEAT_SME_I16I64
140   AEK_HBC =         1ULL << 40, // FEAT_HBC
141   AEK_MOPS =        1ULL << 41, // FEAT_MOPS
142   AEK_PERFMON =     1ULL << 42, // FEAT_PMUv3
143   AEK_SME2 =        1ULL << 43, // FEAT_SME2
144   AEK_SVE2p1 =      1ULL << 44, // FEAT_SVE2p1
145   AEK_SME2p1 =      1ULL << 45, // FEAT_SME2p1
146   AEK_B16B16 =      1ULL << 46, // FEAT_B16B16
147   AEK_SMEF16F16 =   1ULL << 47, // FEAT_SMEF16F16
148   AEK_CSSC =        1ULL << 48, // FEAT_CSSC
149   AEK_RCPC3 =       1ULL << 49, // FEAT_LRCPC3
150   AEK_THE =         1ULL << 50, // FEAT_THE
151   AEK_D128 =        1ULL << 51, // FEAT_D128
152   AEK_LSE128 =      1ULL << 52, // FEAT_LSE128
153   AEK_SPECRES2 =    1ULL << 53, // FEAT_SPECRES2
154   AEK_RASv2 =       1ULL << 54, // FEAT_RASv2
155   AEK_ITE =         1ULL << 55, // FEAT_ITE
156   AEK_GCS =         1ULL << 56, // FEAT_GCS
157 };
158 // clang-format on
159 
160 // Represents an extension that can be enabled with -march=<arch>+<extension>.
161 // Typically these correspond to Arm Architecture extensions, unlike
162 // SubtargetFeature which may represent either an actual extension or some
163 // internal LLVM property.
164 struct ExtensionInfo {
165   StringRef Name;              // Human readable name, e.g. "profile".
166   ArchExtKind ID;              // Corresponding to the ArchExtKind, this
167                                // extensions representation in the bitfield.
168   StringRef Feature;           // -mattr enable string, e.g. "+spe"
169   StringRef NegFeature;        // -mattr disable string, e.g. "-spe"
170   CPUFeatures CPUFeature;      // Function Multi Versioning (FMV) bitfield value
171                                // set in __aarch64_cpu_features
172   StringRef DependentFeatures; // FMV enabled features string,
173                                // e.g. "+dotprod,+fp-armv8,+neon"
174   unsigned FmvPriority;        // FMV feature priority
175   static constexpr unsigned MaxFMVPriority =
176       1000; // Maximum priority for FMV feature
177 };
178 
179 // NOTE: If adding a new extension here, consider adding it to ExtensionMap
180 // in AArch64AsmParser too, if supported as an extension name by binutils.
181 // clang-format off
182 inline constexpr ExtensionInfo Extensions[] = {
183     {"aes", AArch64::AEK_AES, "+aes", "-aes", FEAT_AES, "+fp-armv8,+neon", 150},
184     {"b16b16", AArch64::AEK_B16B16, "+b16b16", "-b16b16", FEAT_MAX, "", 0},
185     {"bf16", AArch64::AEK_BF16, "+bf16", "-bf16", FEAT_BF16, "+bf16", 280},
186     {"brbe", AArch64::AEK_BRBE, "+brbe", "-brbe", FEAT_MAX, "", 0},
187     {"bti", AArch64::AEK_NONE, {}, {}, FEAT_BTI, "+bti", 510},
188     {"crc", AArch64::AEK_CRC, "+crc", "-crc", FEAT_CRC, "+crc", 110},
189     {"crypto", AArch64::AEK_CRYPTO, "+crypto", "-crypto", FEAT_MAX, "+aes,+sha2", 0},
190     {"cssc", AArch64::AEK_CSSC, "+cssc", "-cssc", FEAT_MAX, "", 0},
191     {"d128", AArch64::AEK_D128, "+d128", "-d128", FEAT_MAX, "", 0},
192     {"dgh", AArch64::AEK_NONE, {}, {}, FEAT_DGH, "", 260},
193     {"dit", AArch64::AEK_NONE, {}, {}, FEAT_DIT, "+dit", 180},
194     {"dotprod", AArch64::AEK_DOTPROD, "+dotprod", "-dotprod", FEAT_DOTPROD, "+dotprod,+fp-armv8,+neon", 50},
195     {"dpb", AArch64::AEK_NONE, {}, {}, FEAT_DPB, "+ccpp", 190},
196     {"dpb2", AArch64::AEK_NONE, {}, {}, FEAT_DPB2, "+ccpp,+ccdp", 200},
197     {"ebf16", AArch64::AEK_NONE, {}, {}, FEAT_EBF16, "+bf16", 290},
198     {"f32mm", AArch64::AEK_F32MM, "+f32mm", "-f32mm", FEAT_SVE_F32MM, "+sve,+f32mm,+fullfp16,+fp-armv8,+neon", 350},
199     {"f64mm", AArch64::AEK_F64MM, "+f64mm", "-f64mm", FEAT_SVE_F64MM, "+sve,+f64mm,+fullfp16,+fp-armv8,+neon", 360},
200     {"fcma", AArch64::AEK_NONE, {}, {}, FEAT_FCMA, "+fp-armv8,+neon,+complxnum", 220},
201     {"flagm", AArch64::AEK_FLAGM, "+flagm", "-flagm", FEAT_FLAGM, "+flagm", 20},
202     {"flagm2", AArch64::AEK_NONE, {}, {}, FEAT_FLAGM2, "+flagm,+altnzcv", 30},
203     {"fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8", FEAT_FP, "+fp-armv8,+neon", 90},
204     {"fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16", FEAT_FP16, "+fullfp16,+fp-armv8,+neon", 170},
205     {"fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml", FEAT_FP16FML, "+fp16fml,+fullfp16,+fp-armv8,+neon", 40},
206     {"frintts", AArch64::AEK_NONE, {}, {}, FEAT_FRINTTS, "+fptoint", 250},
207     {"hbc", AArch64::AEK_HBC, "+hbc", "-hbc", FEAT_MAX, "", 0},
208     {"i8mm", AArch64::AEK_I8MM, "+i8mm", "-i8mm", FEAT_I8MM, "+i8mm", 270},
209     {"ite", AArch64::AEK_ITE, "+ite", "-ite", FEAT_MAX, "", 0},
210     {"jscvt", AArch64::AEK_NONE, {}, {}, FEAT_JSCVT, "+fp-armv8,+neon,+jsconv", 210},
211     {"ls64_accdata", AArch64::AEK_NONE, {}, {}, FEAT_LS64_ACCDATA, "+ls64", 540},
212     {"ls64_v", AArch64::AEK_NONE, {}, {}, FEAT_LS64_V, "", 530},
213     {"ls64", AArch64::AEK_LS64, "+ls64", "-ls64", FEAT_LS64, "", 520},
214     {"lse", AArch64::AEK_LSE, "+lse", "-lse", FEAT_LSE, "+lse", 80},
215     {"lse128", AArch64::AEK_LSE128, "+lse128", "-lse128", FEAT_MAX, "", 0},
216     {"memtag", AArch64::AEK_MTE, "+mte", "-mte", FEAT_MEMTAG, "", 440},
217     {"memtag2", AArch64::AEK_NONE, {}, {}, FEAT_MEMTAG2, "+mte", 450},
218     {"memtag3", AArch64::AEK_NONE, {}, {}, FEAT_MEMTAG3, "+mte", 460},
219     {"mops", AArch64::AEK_MOPS, "+mops", "-mops", FEAT_MAX, "", 0},
220     {"pauth", AArch64::AEK_PAUTH, "+pauth", "-pauth", FEAT_MAX, "", 0},
221     {"pmull", AArch64::AEK_NONE, {}, {}, FEAT_PMULL, "+aes,+fp-armv8,+neon", 160},
222     {"pmuv3", AArch64::AEK_PERFMON, "+perfmon", "-perfmon", FEAT_MAX, "", 0},
223     {"predres", AArch64::AEK_PREDRES, "+predres", "-predres", FEAT_PREDRES, "+predres", 480},
224     {"predres2", AArch64::AEK_SPECRES2, "+specres2", "-specres2", FEAT_MAX, "", 0},
225     {"profile", AArch64::AEK_PROFILE, "+spe", "-spe", FEAT_MAX, "", 0},
226     {"ras", AArch64::AEK_RAS, "+ras", "-ras", FEAT_MAX, "", 0},
227     {"rasv2", AArch64::AEK_RASv2, "+rasv2", "-rasv2", FEAT_MAX, "", 0},
228     {"rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc", FEAT_RCPC, "+rcpc", 230},
229     {"rcpc2", AArch64::AEK_NONE, {}, {}, FEAT_RCPC2, "+rcpc", 240},
230     {"rcpc3", AArch64::AEK_RCPC3, "+rcpc3", "-rcpc3", FEAT_MAX, "", 0},
231     {"rdm", AArch64::AEK_RDM, "+rdm", "-rdm", FEAT_RDM, "+rdm,+fp-armv8,+neon", 70},
232     {"rng", AArch64::AEK_RAND, "+rand", "-rand", FEAT_RNG, "+rand", 10},
233     {"rpres", AArch64::AEK_NONE, {}, {}, FEAT_RPRES, "", 300},
234     {"sb", AArch64::AEK_SB, "+sb", "-sb", FEAT_SB, "+sb", 470},
235     {"sha1", AArch64::AEK_NONE, {}, {}, FEAT_SHA1, "+fp-armv8,+neon", 120},
236     {"sha2", AArch64::AEK_SHA2, "+sha2", "-sha2", FEAT_SHA2, "+sha2,+fp-armv8,+neon", 130},
237     {"sha3", AArch64::AEK_SHA3, "+sha3", "-sha3", FEAT_SHA3, "+sha3,+sha2,+fp-armv8,+neon", 140},
238     {"simd", AArch64::AEK_SIMD, "+neon", "-neon", FEAT_SIMD, "+fp-armv8,+neon", 100},
239     {"sm4", AArch64::AEK_SM4, "+sm4", "-sm4", FEAT_SM4, "+sm4,+fp-armv8,+neon", 60},
240     {"sme-f16f16", AArch64::AEK_SMEF16F16, "+sme-f16f16", "-sme-f16f16", FEAT_MAX, "", 0},
241     {"sme-f64f64", AArch64::AEK_SMEF64F64, "+sme-f64f64", "-sme-f64f64", FEAT_SME_F64, "+sme,+sme-f64f64,+bf16", 560},
242     {"sme-i16i64", AArch64::AEK_SMEI16I64, "+sme-i16i64", "-sme-i16i64", FEAT_SME_I64, "+sme,+sme-i16i64,+bf16", 570},
243     {"sme", AArch64::AEK_SME, "+sme", "-sme", FEAT_SME, "+sme,+bf16", 430},
244     {"sme2", AArch64::AEK_SME2, "+sme2", "-sme2", FEAT_SME2, "+sme2,+sme,+bf16", 580},
245     {"sme2p1", AArch64::AEK_SME2p1, "+sme2p1", "-sme2p1", FEAT_MAX, "", 0},
246     {"ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs", FEAT_SSBS, "", 490},
247     {"ssbs2", AArch64::AEK_NONE, {}, {}, FEAT_SSBS2, "+ssbs", 500},
248     {"sve-bf16", AArch64::AEK_NONE, {}, {}, FEAT_SVE_BF16, "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 320},
249     {"sve-ebf16", AArch64::AEK_NONE, {}, {}, FEAT_SVE_EBF16, "+sve,+bf16,+fullfp16,+fp-armv8,+neon", 330},
250     {"sve-i8mm", AArch64::AEK_NONE, {}, {}, FEAT_SVE_I8MM, "+sve,+i8mm,+fullfp16,+fp-armv8,+neon", 340},
251     {"sve", AArch64::AEK_SVE, "+sve", "-sve", FEAT_SVE, "+sve,+fullfp16,+fp-armv8,+neon", 310},
252     {"sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes", FEAT_SVE_AES, "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 380},
253     {"sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm", FEAT_SVE_BITPERM, "+sve2,+sve,+sve2-bitperm,+fullfp16,+fp-armv8,+neon", 400},
254     {"sve2-pmull128", AArch64::AEK_NONE, {}, {}, FEAT_SVE_PMULL128, "+sve2,+sve,+sve2-aes,+fullfp16,+fp-armv8,+neon", 390},
255     {"sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3", FEAT_SVE_SHA3, "+sve2,+sve,+sve2-sha3,+fullfp16,+fp-armv8,+neon", 410},
256     {"sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4", FEAT_SVE_SM4, "+sve2,+sve,+sve2-sm4,+fullfp16,+fp-armv8,+neon", 420},
257     {"sve2", AArch64::AEK_SVE2, "+sve2", "-sve2", FEAT_SVE2, "+sve2,+sve,+fullfp16,+fp-armv8,+neon", 370},
258     {"sve2p1", AArch64::AEK_SVE2p1, "+sve2p1", "-sve2p1", FEAT_MAX, "+sve2p1,+sve2,+sve,+fullfp16,+fp-armv8,+neon", 0},
259     {"the", AArch64::AEK_THE, "+the", "-the", FEAT_MAX, "", 0},
260     {"tme", AArch64::AEK_TME, "+tme", "-tme", FEAT_MAX, "", 0},
261     {"wfxt", AArch64::AEK_NONE, {}, {}, FEAT_WFXT, "+wfxt", 550},
262     {"gcs", AArch64::AEK_GCS, "+gcs", "-gcs", FEAT_MAX, "", 0},
263     // Special cases
264     {"none", AArch64::AEK_NONE, {}, {}, FEAT_MAX, "", ExtensionInfo::MaxFMVPriority},
265 };
266 // clang-format on
267 
268 enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
269 
270 // Information about a specific architecture, e.g. V8.1-A
271 struct ArchInfo {
272   VersionTuple Version;  // Architecture version, major + minor.
273   ArchProfile Profile;   // Architecuture profile
274   StringRef Name;        // Human readable name, e.g. "armv8.1-a"
275   StringRef ArchFeature; // Command line feature flag, e.g. +v8a
276   uint64_t DefaultExts;  // bitfield of default extensions ArchExtKind
277 
278   bool operator==(const ArchInfo &Other) const {
279     return this->Name == Other.Name;
280   }
281   bool operator!=(const ArchInfo &Other) const {
282     return this->Name != Other.Name;
283   }
284 
285   // Defines the following partial order, indicating when an architecture is
286   // a superset of another:
287   //
288   //     v9.4a > v9.3a > v9.3a > v9.3a > v9a;
289   //       v       v       v       v       v
290   //     v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
291   //
292   // v8r has no relation to anything. This is used to determine which
293   // features to enable for a given architecture. See
294   // AArch64TargetInfo::setFeatureEnabled.
295   bool implies(const ArchInfo &Other) const {
296     if (this->Profile != Other.Profile)
297       return false; // ARMV8R
298     if (this->Version.getMajor() == Other.Version.getMajor()) {
299       return this->Version > Other.Version;
300     }
301     if (this->Version.getMajor() == 9 && Other.Version.getMajor() == 8) {
302       assert(this->Version.getMinor() && Other.Version.getMinor() &&
303              "AArch64::ArchInfo should have a minor version.");
304       return this->Version.getMinor().value_or(0) + 5 >=
305              Other.Version.getMinor().value_or(0);
306     }
307     return false;
308   }
309 
310   // Return ArchFeature without the leading "+".
311   StringRef getSubArch() const { return ArchFeature.substr(1); }
312 
313   // Search for ArchInfo by SubArch name
314   static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
315 };
316 
317 // clang-format off
318 inline constexpr ArchInfo ARMV8A    = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", (AArch64::AEK_FP | AArch64::AEK_SIMD), };
319 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)};
320 inline constexpr ArchInfo ARMV8_2A  = { VersionTuple{8, 2}, AProfile, "armv8.2-a", "+v8.2a", (ARMV8_1A.DefaultExts | AArch64::AEK_RAS)};
321 inline constexpr ArchInfo ARMV8_3A  = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts | AArch64::AEK_RCPC)};
322 inline constexpr ArchInfo ARMV8_4A  = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts | AArch64::AEK_DOTPROD)};
323 inline constexpr ArchInfo ARMV8_5A  = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)};
324 inline constexpr ArchInfo ARMV8_6A  = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts | AArch64::AEK_BF16 | AArch64::AEK_I8MM)};
325 inline constexpr ArchInfo ARMV8_7A  = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)};
326 inline constexpr ArchInfo ARMV8_8A  = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts | AArch64::AEK_MOPS | AArch64::AEK_HBC)};
327 inline constexpr ArchInfo ARMV8_9A  = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts | AArch64::AEK_SPECRES2 | AArch64::AEK_CSSC | AArch64::AEK_RASv2)};
328 inline constexpr ArchInfo ARMV9A    = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts | AArch64::AEK_FP16 | AArch64::AEK_SVE | AArch64::AEK_SVE2)};
329 inline constexpr ArchInfo ARMV9_1A  = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts | AArch64::AEK_BF16 | AArch64::AEK_I8MM)};
330 inline constexpr ArchInfo ARMV9_2A  = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)};
331 inline constexpr ArchInfo ARMV9_3A  = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts | AArch64::AEK_MOPS | AArch64::AEK_HBC)};
332 inline constexpr ArchInfo ARMV9_4A  = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts | AArch64::AEK_SPECRES2 | AArch64::AEK_CSSC | AArch64::AEK_RASv2)};
333 // For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions.
334 inline constexpr ArchInfo ARMV8R    = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", ((ARMV8_5A.DefaultExts ^ AArch64::AEK_LSE) | AArch64::AEK_SSBS | AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SB), };
335 // clang-format on
336 
337 // The set of all architectures
338 static constexpr std::array<const ArchInfo *, 16> ArchInfos = {
339     &ARMV8A,   &ARMV8_1A, &ARMV8_2A, &ARMV8_3A, &ARMV8_4A, &ARMV8_5A,
340     &ARMV8_6A, &ARMV8_7A, &ARMV8_8A, &ARMV8_9A, &ARMV9A, &ARMV9_1A,
341     &ARMV9_2A, &ARMV9_3A, &ARMV9_4A, &ARMV8R,
342 };
343 
344 // Details of a specific CPU.
345 struct CpuInfo {
346   StringRef Name; // Name, as written for -mcpu.
347   const ArchInfo &Arch;
348   uint64_t DefaultExtensions; // Default extensions for this CPU. These will be
349                               // ORd with the architecture defaults.
350 
351   uint64_t getImpliedExtensions() const {
352     return DefaultExtensions | Arch.DefaultExts;
353   }
354 };
355 
356 inline constexpr CpuInfo CpuInfos[] = {
357     {"cortex-a34", ARMV8A,
358      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
359     {"cortex-a35", ARMV8A,
360      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
361     {"cortex-a53", ARMV8A,
362      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
363     {"cortex-a55", ARMV8_2A,
364      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
365       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)},
366     {"cortex-a510", ARMV9A,
367      (AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SB |
368       AArch64::AEK_PAUTH | AArch64::AEK_MTE | AArch64::AEK_SSBS |
369       AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
370       AArch64::AEK_FP16FML)},
371     {"cortex-a57", ARMV8A,
372      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
373     {"cortex-a65", ARMV8_2A,
374      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
375       AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
376     {"cortex-a65ae", ARMV8_2A,
377      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
378       AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
379     {"cortex-a72", ARMV8A,
380      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
381     {"cortex-a73", ARMV8A,
382      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
383     {"cortex-a75", ARMV8_2A,
384      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
385       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)},
386     {"cortex-a76", ARMV8_2A,
387      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
388       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
389     {"cortex-a76ae", ARMV8_2A,
390      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
391       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
392     {"cortex-a77", ARMV8_2A,
393      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
394       AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_SSBS)},
395     {"cortex-a78", ARMV8_2A,
396      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
397       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS |
398       AArch64::AEK_PROFILE)},
399     {"cortex-a78c", ARMV8_2A,
400      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
401       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS |
402       AArch64::AEK_PROFILE | AArch64::AEK_FLAGM | AArch64::AEK_PAUTH |
403       AArch64::AEK_FP16FML)},
404     {"cortex-a710", ARMV9A,
405      (AArch64::AEK_MTE | AArch64::AEK_PAUTH | AArch64::AEK_FLAGM |
406       AArch64::AEK_SB | AArch64::AEK_I8MM | AArch64::AEK_FP16FML |
407       AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
408       AArch64::AEK_BF16)},
409     {"cortex-a715", ARMV9A,
410      (AArch64::AEK_SB | AArch64::AEK_SSBS | AArch64::AEK_MTE |
411       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PAUTH |
412       AArch64::AEK_I8MM | AArch64::AEK_PREDRES | AArch64::AEK_PERFMON |
413       AArch64::AEK_PROFILE | AArch64::AEK_SVE | AArch64::AEK_SVE2BITPERM |
414       AArch64::AEK_BF16 | AArch64::AEK_FLAGM)},
415     {"cortex-r82", ARMV8R, (AArch64::AEK_LSE)},
416     {"cortex-x1", ARMV8_2A,
417      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
418       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS |
419       AArch64::AEK_PROFILE)},
420     {"cortex-x1c", ARMV8_2A,
421      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
422       AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | AArch64::AEK_SSBS |
423       AArch64::AEK_PAUTH | AArch64::AEK_PROFILE)},
424     {"cortex-x2", ARMV9A,
425      (AArch64::AEK_MTE | AArch64::AEK_BF16 | AArch64::AEK_I8MM |
426       AArch64::AEK_PAUTH | AArch64::AEK_SSBS | AArch64::AEK_SB |
427       AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM |
428       AArch64::AEK_FP16FML)},
429     {"cortex-x3", ARMV9A,
430      (AArch64::AEK_SVE | AArch64::AEK_PERFMON | AArch64::AEK_PROFILE |
431       AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_MTE |
432       AArch64::AEK_SVE2BITPERM | AArch64::AEK_SB | AArch64::AEK_PAUTH |
433       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PREDRES |
434       AArch64::AEK_FLAGM | AArch64::AEK_SSBS)},
435     {"neoverse-e1", ARMV8_2A,
436      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
437       AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_SSBS)},
438     {"neoverse-n1", ARMV8_2A,
439      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
440       AArch64::AEK_FP16 | AArch64::AEK_PROFILE | AArch64::AEK_RCPC |
441       AArch64::AEK_SSBS)},
442     {"neoverse-n2", ARMV8_5A,
443      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
444       AArch64::AEK_SM4 | AArch64::AEK_BF16 | AArch64::AEK_DOTPROD |
445       AArch64::AEK_FP16 | AArch64::AEK_I8MM | AArch64::AEK_MTE |
446       AArch64::AEK_SB | AArch64::AEK_SSBS | AArch64::AEK_SVE |
447       AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM)},
448     {"neoverse-512tvb", ARMV8_4A,
449      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
450       AArch64::AEK_SM4 | AArch64::AEK_SVE | AArch64::AEK_SSBS |
451       AArch64::AEK_FP16 | AArch64::AEK_BF16 | AArch64::AEK_DOTPROD |
452       AArch64::AEK_PROFILE | AArch64::AEK_RAND | AArch64::AEK_FP16FML |
453       AArch64::AEK_I8MM)},
454     {"neoverse-v1", ARMV8_4A,
455      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
456       AArch64::AEK_SM4 | AArch64::AEK_SVE | AArch64::AEK_SSBS |
457       AArch64::AEK_FP16 | AArch64::AEK_BF16 | AArch64::AEK_DOTPROD |
458       AArch64::AEK_PROFILE | AArch64::AEK_RAND | AArch64::AEK_FP16FML |
459       AArch64::AEK_I8MM)},
460     {"neoverse-v2", ARMV9A,
461      (AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SSBS |
462       AArch64::AEK_FP16 | AArch64::AEK_BF16 | AArch64::AEK_RAND |
463       AArch64::AEK_DOTPROD | AArch64::AEK_PROFILE | AArch64::AEK_SVE2BITPERM |
464       AArch64::AEK_FP16FML | AArch64::AEK_I8MM | AArch64::AEK_MTE)},
465     {"cyclone", ARMV8A,
466      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_NONE)},
467     {"apple-a7", ARMV8A,
468      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_NONE)},
469     {"apple-a8", ARMV8A,
470      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_NONE)},
471     {"apple-a9", ARMV8A,
472      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_NONE)},
473     {"apple-a10", ARMV8A,
474      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC |
475       AArch64::AEK_RDM)},
476     {"apple-a11", ARMV8_2A,
477      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16)},
478     {"apple-a12", ARMV8_3A,
479      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16)},
480     {"apple-a13", ARMV8_4A,
481      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
482       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
483     {"apple-a14", ARMV8_5A,
484      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
485       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
486     {"apple-a15", ARMV8_5A,
487      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
488       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
489       AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
490     {"apple-a16", ARMV8_5A,
491      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
492       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
493       AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
494     {"apple-m1", ARMV8_5A,
495      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
496       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3)},
497     {"apple-m2", ARMV8_5A,
498      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
499       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_SHA3 |
500       AArch64::AEK_BF16 | AArch64::AEK_I8MM)},
501     {"apple-s4", ARMV8_3A,
502      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16)},
503     {"apple-s5", ARMV8_3A,
504      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16)},
505     {"exynos-m3", ARMV8A,
506      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
507     {"exynos-m4", ARMV8_2A,
508      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
509       AArch64::AEK_FP16)},
510     {"exynos-m5", ARMV8_2A,
511      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
512       AArch64::AEK_FP16)},
513     {"falkor", ARMV8A,
514      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC |
515       AArch64::AEK_RDM)},
516     {"saphira", ARMV8_3A,
517      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_PROFILE)},
518     {"kryo", ARMV8A, (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
519     {"thunderx2t99", ARMV8_1A, (AArch64::AEK_AES | AArch64::AEK_SHA2)},
520     {"thunderx3t110", ARMV8_3A, (AArch64::AEK_AES | AArch64::AEK_SHA2)},
521     {"thunderx", ARMV8A,
522      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
523     {"thunderxt88", ARMV8A,
524      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
525     {"thunderxt81", ARMV8A,
526      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
527     {"thunderxt83", ARMV8A,
528      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_CRC)},
529     {"tsv110", ARMV8_2A,
530      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_DOTPROD |
531       AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PROFILE)},
532     {"a64fx", ARMV8_2A,
533      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16 |
534       AArch64::AEK_SVE)},
535     {"carmel", ARMV8_2A,
536      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_FP16)},
537     {"ampere1", ARMV8_6A,
538      (AArch64::AEK_AES | AArch64::AEK_SHA2 | AArch64::AEK_SHA3 |
539       AArch64::AEK_FP16 | AArch64::AEK_SB | AArch64::AEK_SSBS |
540       AArch64::AEK_RAND)},
541     {"ampere1a", ARMV8_6A,
542      (AArch64::AEK_FP16 | AArch64::AEK_RAND | AArch64::AEK_SM4 |
543       AArch64::AEK_SHA3 | AArch64::AEK_SHA2 | AArch64::AEK_AES |
544       AArch64::AEK_MTE | AArch64::AEK_SB | AArch64::AEK_SSBS)},
545 };
546 
547 // An alias for a CPU.
548 struct CpuAlias {
549   StringRef Alias;
550   StringRef Name;
551 };
552 
553 inline constexpr CpuAlias CpuAliases[] = {{"grace", "neoverse-v2"}};
554 
555 bool getExtensionFeatures(uint64_t Extensions,
556                           std::vector<StringRef> &Features);
557 
558 StringRef getArchExtFeature(StringRef ArchExt);
559 StringRef resolveCPUAlias(StringRef CPU);
560 
561 // Information by Name
562 std::optional<ArchInfo> getArchForCpu(StringRef CPU);
563 
564 // Parser
565 std::optional<ArchInfo> parseArch(StringRef Arch);
566 std::optional<ExtensionInfo> parseArchExtension(StringRef Extension);
567 // Given the name of a CPU or alias, return the correponding CpuInfo.
568 std::optional<CpuInfo> parseCpu(StringRef Name);
569 // Used by target parser tests
570 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
571 
572 bool isX18ReservedByDefault(const Triple &TT);
573 
574 // For given feature names, return a bitmask corresponding to the entries of
575 // AArch64::CPUFeatures. The values in CPUFeatures are not bitmasks
576 // themselves, they are sequential (0, 1, 2, 3, ...).
577 uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
578 
579 } // namespace AArch64
580 } // namespace llvm
581 
582 #endif
583