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