xref: /llvm-project/llvm/unittests/TargetParser/TargetParserTest.cpp (revision 5ec7ecd2f2d213f1777af3ff3a2e7910d00ea774)
1 //===----------- TargetParser.cpp - Target Parser -------------------------===//
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 #include "llvm/TargetParser/TargetParser.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/Support/ARMBuildAttributes.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/FormatVariadic.h"
16 #include "llvm/TargetParser/AArch64TargetParser.h"
17 #include "llvm/TargetParser/ARMTargetParser.h"
18 #include "llvm/TargetParser/ARMTargetParserCommon.h"
19 #include "llvm/TargetParser/Triple.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include <optional>
23 #include <sstream>
24 #include <string>
25 
26 using namespace llvm;
27 
28 using ::testing::Contains;
29 using ::testing::StrEq;
30 
31 namespace {
32 const char *ARMArch[] = {
33     "armv4",       "armv4t",    "armv5",        "armv5t",      "armv5e",
34     "armv5te",     "armv5tej",  "armv6",        "armv6j",      "armv6k",
35     "armv6hl",     "armv6t2",   "armv6kz",      "armv6z",      "armv6zk",
36     "armv6-m",     "armv6m",    "armv6sm",      "armv6s-m",    "armv7-a",
37     "armv7",       "armv7a",    "armv7ve",      "armv7hl",     "armv7l",
38     "armv7-r",     "armv7r",    "armv7-m",      "armv7m",      "armv7k",
39     "armv7s",      "armv7e-m",  "armv7em",      "armv8-a",     "armv8",
40     "armv8a",      "armv8l",    "armv8.1-a",    "armv8.1a",    "armv8.2-a",
41     "armv8.2a",    "armv8.3-a", "armv8.3a",     "armv8.4-a",   "armv8.4a",
42     "armv8.5-a",   "armv8.5a",  "armv8.6-a",    "armv8.6a",    "armv8.7-a",
43     "armv8.7a",    "armv8.8-a", "armv8.8a",     "armv8.9-a",   "armv8.9a",
44     "armv8-r",     "armv8r",    "armv8-m.base", "armv8m.base", "armv8-m.main",
45     "armv8m.main", "iwmmxt",    "iwmmxt2",      "xscale",      "armv8.1-m.main",
46     "armv9-a",     "armv9",     "armv9a",       "armv9.1-a",   "armv9.1a",
47     "armv9.2-a",   "armv9.2a",  "armv9.3-a",    "armv9.3a",    "armv9.4-a",
48     "armv9.4a",    "armv9.5-a", "armv9.5a",     "armv9.6a",    "armv9.6-a",
49 };
50 
51 std::string FormatExtensionFlags(int64_t Flags) {
52   std::vector<StringRef> Features;
53 
54   if (Flags & ARM::AEK_NONE)
55     Features.push_back("none");
56   ARM::getExtensionFeatures(Flags, Features);
57 
58   // The target parser also includes every extension you don't have.
59   // E.g. if AEK_CRC is not set then it adds "-crc". Not useful here.
60   Features.erase(std::remove_if(Features.begin(), Features.end(),
61                                 [](StringRef extension) {
62                                   return extension.starts_with("-");
63                                 }),
64                  Features.end());
65 
66   return llvm::join(Features, ", ");
67 }
68 
69 std::string SerializeExtensionFlags(AArch64::ExtensionBitset Flags) {
70   std::string SerializedFlags;
71   std::ostringstream ss;
72   int HexValue = 0;
73   for (unsigned int i = 0; i < AArch64::AEK_NUM_EXTENSIONS; i++) {
74     HexValue <<= 1;
75     HexValue |= (int)Flags[i];
76     if ((i + 1) % 4 == 0) {
77       ss << std::hex << HexValue;
78       HexValue = 0;
79     }
80   }
81   // check if there are remainig unhandled bits
82   if ((AArch64::AEK_NUM_EXTENSIONS % 4) != 0)
83     ss << std::hex << HexValue;
84 
85   SerializedFlags = ss.str();
86   return SerializedFlags;
87 }
88 
89 template <ARM::ISAKind ISAKind> struct AssertSameExtensionFlags {
90   AssertSameExtensionFlags(StringRef CPUName) : CPUName(CPUName) {}
91 
92   testing::AssertionResult operator()(const char *m_expr, const char *n_expr,
93                                       uint64_t ExpectedFlags,
94                                       uint64_t GotFlags) {
95     if (ExpectedFlags == GotFlags)
96       return testing::AssertionSuccess();
97 
98     return testing::AssertionFailure()
99            << llvm::formatv("CPU: {4}\n"
100                             "Expected extension flags: {0} ({1:x})\n"
101                             "     Got extension flags: {2} ({3:x})\n"
102                             "                    Diff: {5} ({6:x})\n",
103                             FormatExtensionFlags(ExpectedFlags), ExpectedFlags,
104                             FormatExtensionFlags(GotFlags), GotFlags, CPUName,
105                             FormatExtensionFlags(ExpectedFlags ^ GotFlags));
106   }
107 private:
108   StringRef CPUName;
109 };
110 
111 template <typename T> struct ARMCPUTestParams {
112   ARMCPUTestParams(StringRef CPUName, StringRef ExpectedArch,
113                    StringRef ExpectedFPU, T ExpectedFlags, StringRef CPUAttr)
114       : CPUName(CPUName), ExpectedArch(ExpectedArch), ExpectedFPU(ExpectedFPU),
115         ExpectedFlags(ExpectedFlags), CPUAttr(CPUAttr) {}
116 
117   friend std::ostream &operator<<(std::ostream &os,
118                                   const ARMCPUTestParams<T> &params) {
119     os << "\"" << params.CPUName.str() << "\", \"" << params.ExpectedArch.str()
120        << "\", \"" << params.ExpectedFPU.str() << "\", 0x";
121     if constexpr (std::is_same<T, uint64_t>::value)
122       os << std::hex << params.ExpectedFlags;
123     else
124       os << SerializeExtensionFlags(params.ExpectedFlags);
125     os << ", \"" << params.CPUAttr.str() << "\"";
126     return os;
127   }
128 
129   /// Print a gtest-compatible facsimile of the CPUName, to make the test's name
130   /// human-readable.
131   ///
132   /// https://github.com/google/googletest/blob/main/docs/advanced.md#specifying-names-for-value-parameterized-test-parameters
133   static std::string PrintToStringParamName(
134       const testing::TestParamInfo<ARMCPUTestParams<T>> &Info) {
135     std::string Name = Info.param.CPUName.str();
136     for (char &C : Name)
137       if (!std::isalnum(C))
138         C = '_';
139     return Name;
140   }
141 
142   StringRef CPUName;
143   StringRef ExpectedArch;
144   StringRef ExpectedFPU;
145   T ExpectedFlags;
146   StringRef CPUAttr;
147 };
148 
149 class ARMCPUTestFixture
150     : public ::testing::TestWithParam<ARMCPUTestParams<uint64_t>> {};
151 
152 TEST_P(ARMCPUTestFixture, ARMCPUTests) {
153   auto params = GetParam();
154 
155   ARM::ArchKind AK = ARM::parseCPUArch(params.CPUName);
156   EXPECT_EQ(params.ExpectedArch, ARM::getArchName(AK));
157 
158   ARM::FPUKind FPUKind = ARM::getDefaultFPU(params.CPUName, AK);
159   EXPECT_EQ(params.ExpectedFPU, ARM::getFPUName(FPUKind));
160 
161   uint64_t default_extensions = ARM::getDefaultExtensions(params.CPUName, AK);
162   EXPECT_PRED_FORMAT2(
163       AssertSameExtensionFlags<ARM::ISAKind::ARM>(params.CPUName),
164       params.ExpectedFlags, default_extensions);
165 
166   EXPECT_EQ(params.CPUAttr, ARM::getCPUAttr(AK));
167 }
168 
169 // Note that we include ARM::AEK_NONE even when there are other extensions
170 // we expect. This is because the default extensions for a CPU are the sum
171 // of the default extensions for its architecture and for the CPU.
172 // So if a CPU has no extra extensions, it adds AEK_NONE.
173 INSTANTIATE_TEST_SUITE_P(
174     ARMCPUTestsPart1, ARMCPUTestFixture,
175     ::testing::Values(
176         ARMCPUTestParams<uint64_t>("invalid", "invalid", "invalid",
177                                    ARM::AEK_NONE, ""),
178         ARMCPUTestParams<uint64_t>("generic", "invalid", "none", ARM::AEK_NONE,
179                                    ""),
180 
181         ARMCPUTestParams<uint64_t>("arm8", "armv4", "none", ARM::AEK_NONE, "4"),
182         ARMCPUTestParams<uint64_t>("arm810", "armv4", "none", ARM::AEK_NONE,
183                                    "4"),
184         ARMCPUTestParams<uint64_t>("strongarm", "armv4", "none", ARM::AEK_NONE,
185                                    "4"),
186         ARMCPUTestParams<uint64_t>("strongarm110", "armv4", "none",
187                                    ARM::AEK_NONE, "4"),
188         ARMCPUTestParams<uint64_t>("strongarm1100", "armv4", "none",
189                                    ARM::AEK_NONE, "4"),
190         ARMCPUTestParams<uint64_t>("strongarm1110", "armv4", "none",
191                                    ARM::AEK_NONE, "4"),
192         ARMCPUTestParams<uint64_t>("arm7tdmi", "armv4t", "none", ARM::AEK_NONE,
193                                    "4T"),
194         ARMCPUTestParams<uint64_t>("arm7tdmi-s", "armv4t", "none",
195                                    ARM::AEK_NONE, "4T"),
196         ARMCPUTestParams<uint64_t>("arm710t", "armv4t", "none", ARM::AEK_NONE,
197                                    "4T"),
198         ARMCPUTestParams<uint64_t>("arm720t", "armv4t", "none", ARM::AEK_NONE,
199                                    "4T"),
200         ARMCPUTestParams<uint64_t>("arm9", "armv4t", "none", ARM::AEK_NONE,
201                                    "4T"),
202         ARMCPUTestParams<uint64_t>("arm9tdmi", "armv4t", "none", ARM::AEK_NONE,
203                                    "4T"),
204         ARMCPUTestParams<uint64_t>("arm920", "armv4t", "none", ARM::AEK_NONE,
205                                    "4T"),
206         ARMCPUTestParams<uint64_t>("arm920t", "armv4t", "none", ARM::AEK_NONE,
207                                    "4T"),
208         ARMCPUTestParams<uint64_t>("arm922t", "armv4t", "none", ARM::AEK_NONE,
209                                    "4T"),
210         ARMCPUTestParams<uint64_t>("arm940t", "armv4t", "none", ARM::AEK_NONE,
211                                    "4T"),
212         ARMCPUTestParams<uint64_t>("ep9312", "armv4t", "none", ARM::AEK_NONE,
213                                    "4T"),
214         ARMCPUTestParams<uint64_t>("arm10tdmi", "armv5t", "none", ARM::AEK_NONE,
215                                    "5T"),
216         ARMCPUTestParams<uint64_t>("arm1020t", "armv5t", "none", ARM::AEK_NONE,
217                                    "5T"),
218         ARMCPUTestParams<uint64_t>("arm9e", "armv5te", "none",
219                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
220         ARMCPUTestParams<uint64_t>("arm946e-s", "armv5te", "none",
221                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
222         ARMCPUTestParams<uint64_t>("arm966e-s", "armv5te", "none",
223                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
224         ARMCPUTestParams<uint64_t>("arm968e-s", "armv5te", "none",
225                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
226         ARMCPUTestParams<uint64_t>("arm10e", "armv5te", "none",
227                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
228         ARMCPUTestParams<uint64_t>("arm1020e", "armv5te", "none",
229                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
230         ARMCPUTestParams<uint64_t>("arm1022e", "armv5te", "none",
231                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TE"),
232         ARMCPUTestParams<uint64_t>("arm926ej-s", "armv5tej", "none",
233                                    ARM::AEK_NONE | ARM::AEK_DSP, "5TEJ"),
234         ARMCPUTestParams<uint64_t>("arm1136j-s", "armv6", "none",
235                                    ARM::AEK_NONE | ARM::AEK_DSP, "6"),
236         ARMCPUTestParams<uint64_t>("arm1136jf-s", "armv6", "vfpv2",
237                                    ARM::AEK_NONE | ARM::AEK_DSP, "6"),
238         ARMCPUTestParams<uint64_t>("arm1176jz-s", "armv6kz", "none",
239                                    ARM::AEK_NONE | ARM::AEK_SEC | ARM::AEK_DSP,
240                                    "6KZ"),
241         ARMCPUTestParams<uint64_t>("mpcore", "armv6k", "vfpv2",
242                                    ARM::AEK_NONE | ARM::AEK_DSP, "6K"),
243         ARMCPUTestParams<uint64_t>("mpcorenovfp", "armv6k", "none",
244                                    ARM::AEK_NONE | ARM::AEK_DSP, "6K"),
245         ARMCPUTestParams<uint64_t>("arm1176jzf-s", "armv6kz", "vfpv2",
246                                    ARM::AEK_NONE | ARM::AEK_SEC | ARM::AEK_DSP,
247                                    "6KZ"),
248         ARMCPUTestParams<uint64_t>("arm1156t2-s", "armv6t2", "none",
249                                    ARM::AEK_NONE | ARM::AEK_DSP, "6T2"),
250         ARMCPUTestParams<uint64_t>("arm1156t2f-s", "armv6t2", "vfpv2",
251                                    ARM::AEK_NONE | ARM::AEK_DSP, "6T2"),
252         ARMCPUTestParams<uint64_t>("cortex-m0", "armv6-m", "none",
253                                    ARM::AEK_NONE, "6-M"),
254         ARMCPUTestParams<uint64_t>("cortex-m0plus", "armv6-m", "none",
255                                    ARM::AEK_NONE, "6-M"),
256         ARMCPUTestParams<uint64_t>("cortex-m1", "armv6-m", "none",
257                                    ARM::AEK_NONE, "6-M"),
258         ARMCPUTestParams<uint64_t>("sc000", "armv6-m", "none", ARM::AEK_NONE,
259                                    "6-M"),
260         ARMCPUTestParams<uint64_t>("cortex-a5", "armv7-a", "neon-vfpv4",
261                                    ARM::AEK_MP | ARM::AEK_SEC | ARM::AEK_DSP,
262                                    "7-A"),
263         ARMCPUTestParams<uint64_t>("cortex-a7", "armv7-a", "neon-vfpv4",
264                                    ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM |
265                                        ARM::AEK_MP | ARM::AEK_SEC |
266                                        ARM::AEK_VIRT | ARM::AEK_DSP,
267                                    "7-A"),
268         ARMCPUTestParams<uint64_t>("cortex-a8", "armv7-a", "neon",
269                                    ARM::AEK_SEC | ARM::AEK_DSP, "7-A")),
270     ARMCPUTestParams<uint64_t>::PrintToStringParamName);
271 
272 // gtest in llvm has a limit of 50 test cases when using ::Values so we split
273 // them into 2 blocks
274 INSTANTIATE_TEST_SUITE_P(
275     ARMCPUTestsPart2, ARMCPUTestFixture,
276     ::testing::Values(
277         ARMCPUTestParams<uint64_t>("cortex-a9", "armv7-a", "neon-fp16",
278                                    ARM::AEK_MP | ARM::AEK_SEC | ARM::AEK_DSP,
279                                    "7-A"),
280         ARMCPUTestParams<uint64_t>("cortex-a12", "armv7-a", "neon-vfpv4",
281                                    ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
282                                        ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
283                                        ARM::AEK_DSP,
284                                    "7-A"),
285         ARMCPUTestParams<uint64_t>("cortex-a15", "armv7-a", "neon-vfpv4",
286                                    ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
287                                        ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
288                                        ARM::AEK_DSP,
289                                    "7-A"),
290         ARMCPUTestParams<uint64_t>("cortex-a17", "armv7-a", "neon-vfpv4",
291                                    ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
292                                        ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
293                                        ARM::AEK_DSP,
294                                    "7-A"),
295         ARMCPUTestParams<uint64_t>("krait", "armv7-a", "neon-vfpv4",
296                                    ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
297                                        ARM::AEK_DSP,
298                                    "7-A"),
299         ARMCPUTestParams<uint64_t>("cortex-r4", "armv7-r", "none",
300                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB |
301                                        ARM::AEK_DSP,
302                                    "7-R"),
303         ARMCPUTestParams<uint64_t>("cortex-r4f", "armv7-r", "vfpv3-d16",
304                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB |
305                                        ARM::AEK_DSP,
306                                    "7-R"),
307         ARMCPUTestParams<uint64_t>("cortex-r5", "armv7-r", "vfpv3-d16",
308                                    ARM::AEK_MP | ARM::AEK_HWDIVARM |
309                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
310                                    "7-R"),
311         ARMCPUTestParams<uint64_t>("cortex-r7", "armv7-r", "vfpv3-d16-fp16",
312                                    ARM::AEK_MP | ARM::AEK_HWDIVARM |
313                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
314                                    "7-R"),
315         ARMCPUTestParams<uint64_t>("cortex-r8", "armv7-r", "vfpv3-d16-fp16",
316                                    ARM::AEK_MP | ARM::AEK_HWDIVARM |
317                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
318                                    "7-R"),
319         ARMCPUTestParams<uint64_t>("cortex-r52", "armv8-r", "neon-fp-armv8",
320                                    ARM::AEK_NONE | ARM::AEK_CRC | ARM::AEK_MP |
321                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
322                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
323                                    "8-R"),
324         ARMCPUTestParams<uint64_t>("cortex-r52plus", "armv8-r", "neon-fp-armv8",
325                                    ARM::AEK_NONE | ARM::AEK_CRC | ARM::AEK_MP |
326                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
327                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
328                                    "8-R"),
329         ARMCPUTestParams<uint64_t>("sc300", "armv7-m", "none",
330                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB, "7-M"),
331         ARMCPUTestParams<uint64_t>("cortex-m3", "armv7-m", "none",
332                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB, "7-M"),
333         ARMCPUTestParams<uint64_t>("cortex-m4", "armv7e-m", "fpv4-sp-d16",
334                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB |
335                                        ARM::AEK_DSP,
336                                    "7E-M"),
337         ARMCPUTestParams<uint64_t>("cortex-m7", "armv7e-m", "fpv5-d16",
338                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB |
339                                        ARM::AEK_DSP,
340                                    "7E-M"),
341         ARMCPUTestParams<uint64_t>("cortex-a32", "armv8-a",
342                                    "crypto-neon-fp-armv8",
343                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
344                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
345                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
346                                    "8-A"),
347         ARMCPUTestParams<uint64_t>("cortex-a35", "armv8-a",
348                                    "crypto-neon-fp-armv8",
349                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
350                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
351                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
352                                    "8-A"),
353         ARMCPUTestParams<uint64_t>("cortex-a53", "armv8-a",
354                                    "crypto-neon-fp-armv8",
355                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
356                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
357                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
358                                    "8-A"),
359         ARMCPUTestParams<uint64_t>(
360             "cortex-a55", "armv8.2-a", "crypto-neon-fp-armv8",
361             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
362                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
363                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
364             "8.2-A"),
365         ARMCPUTestParams<uint64_t>("cortex-a57", "armv8-a",
366                                    "crypto-neon-fp-armv8",
367                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
368                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
369                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
370                                    "8-A"),
371         ARMCPUTestParams<uint64_t>("cortex-a72", "armv8-a",
372                                    "crypto-neon-fp-armv8",
373                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
374                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
375                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
376                                    "8-A"),
377         ARMCPUTestParams<uint64_t>("cortex-a73", "armv8-a",
378                                    "crypto-neon-fp-armv8",
379                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
380                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
381                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
382                                    "8-A"),
383         ARMCPUTestParams<uint64_t>(
384             "cortex-a75", "armv8.2-a", "crypto-neon-fp-armv8",
385             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
386                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
387                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
388             "8.2-A"),
389         ARMCPUTestParams<uint64_t>(
390             "cortex-a76", "armv8.2-a", "crypto-neon-fp-armv8",
391             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
392                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
393                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
394             "8.2-A"),
395         ARMCPUTestParams<uint64_t>(
396             "cortex-a76ae", "armv8.2-a", "crypto-neon-fp-armv8",
397             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
398                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
399                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
400             "8.2-A"),
401         ARMCPUTestParams<uint64_t>(
402             "cortex-a78c", "armv8.2-a", "crypto-neon-fp-armv8",
403             ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
404                 ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC |
405                 ARM::AEK_RAS | ARM::AEK_FP16 | ARM::AEK_DOTPROD,
406             "8.2-A"),
407         ARMCPUTestParams<uint64_t>("cortex-a510", "armv9-a", "neon-fp-armv8",
408                                    ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
409                                        ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
410                                        ARM::AEK_DSP | ARM::AEK_CRC |
411                                        ARM::AEK_RAS | ARM::AEK_DOTPROD |
412                                        ARM::AEK_FP16FML | ARM::AEK_BF16 |
413                                        ARM::AEK_I8MM | ARM::AEK_SB,
414                                    "9-A"),
415         ARMCPUTestParams<uint64_t>("cortex-a710", "armv9-a", "neon-fp-armv8",
416                                    ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
417                                        ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
418                                        ARM::AEK_DSP | ARM::AEK_CRC |
419                                        ARM::AEK_RAS | ARM::AEK_DOTPROD |
420                                        ARM::AEK_FP16FML | ARM::AEK_BF16 |
421                                        ARM::AEK_I8MM | ARM::AEK_SB,
422                                    "9-A"),
423         ARMCPUTestParams<uint64_t>(
424             "cortex-a77", "armv8.2-a", "crypto-neon-fp-armv8",
425             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
426                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
427                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
428             "8.2-A"),
429         ARMCPUTestParams<uint64_t>(
430             "cortex-a78", "armv8.2-a", "crypto-neon-fp-armv8",
431             ARM::AEK_DOTPROD | ARM::AEK_FP16 | ARM::AEK_SEC | ARM::AEK_MP |
432                 ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
433                 ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS,
434             "8.2-A"),
435         ARMCPUTestParams<uint64_t>(
436             "cortex-a78ae", "armv8.2-a", "crypto-neon-fp-armv8",
437             ARM::AEK_RAS | ARM::AEK_DOTPROD | ARM::AEK_SEC | ARM::AEK_MP |
438                 ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
439                 ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS,
440             "8.2-A"),
441         ARMCPUTestParams<uint64_t>(
442             "cortex-x1", "armv8.2-a", "crypto-neon-fp-armv8",
443             ARM::AEK_RAS | ARM::AEK_FP16 | ARM::AEK_DOTPROD | ARM::AEK_SEC |
444                 ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
445                 ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC,
446             "8.2-A"),
447         ARMCPUTestParams<uint64_t>(
448             "cortex-x1c", "armv8.2-a", "crypto-neon-fp-armv8",
449             ARM::AEK_RAS | ARM::AEK_FP16 | ARM::AEK_DOTPROD | ARM::AEK_SEC |
450                 ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
451                 ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC,
452             "8.2-A"),
453         ARMCPUTestParams<uint64_t>(
454             "neoverse-n1", "armv8.2-a", "crypto-neon-fp-armv8",
455             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
456                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
457                 ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_DOTPROD,
458             "8.2-A"),
459         ARMCPUTestParams<uint64_t>(
460             "neoverse-n2", "armv9-a", "neon-fp-armv8",
461             ARM::AEK_CRC | ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM |
462                 ARM::AEK_MP | ARM::AEK_SEC | ARM::AEK_VIRT | ARM::AEK_DSP |
463                 ARM::AEK_BF16 | ARM::AEK_DOTPROD | ARM::AEK_RAS |
464                 ARM::AEK_I8MM | ARM::AEK_FP16FML | ARM::AEK_SB,
465             "9-A"),
466         ARMCPUTestParams<uint64_t>(
467             "neoverse-v1", "armv8.4-a", "crypto-neon-fp-armv8",
468             ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
469                 ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC |
470                 ARM::AEK_RAS | ARM::AEK_FP16 | ARM::AEK_BF16 | ARM::AEK_DOTPROD,
471             "8.4-A"),
472         ARMCPUTestParams<uint64_t>("cyclone", "armv8-a", "crypto-neon-fp-armv8",
473                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
474                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
475                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
476                                    "8-A"),
477         ARMCPUTestParams<uint64_t>("exynos-m3", "armv8-a",
478                                    "crypto-neon-fp-armv8",
479                                    ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
480                                        ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
481                                        ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
482                                    "8-A"),
483         ARMCPUTestParams<uint64_t>(
484             "exynos-m4", "armv8.2-a", "crypto-neon-fp-armv8",
485             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
486                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
487                 ARM::AEK_DOTPROD | ARM::AEK_FP16 | ARM::AEK_RAS,
488             "8.2-A"),
489         ARMCPUTestParams<uint64_t>(
490             "exynos-m5", "armv8.2-a", "crypto-neon-fp-armv8",
491             ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
492                 ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP |
493                 ARM::AEK_DOTPROD | ARM::AEK_FP16 | ARM::AEK_RAS,
494             "8.2-A"),
495         ARMCPUTestParams<uint64_t>("cortex-m23", "armv8-m.base", "none",
496                                    ARM::AEK_NONE | ARM::AEK_HWDIVTHUMB,
497                                    "8-M.Baseline"),
498         ARMCPUTestParams<uint64_t>("cortex-m33", "armv8-m.main", "fpv5-sp-d16",
499                                    ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
500                                    "8-M.Mainline"),
501         ARMCPUTestParams<uint64_t>("star-mc1", "armv8-m.main", "fpv5-sp-d16",
502                                    ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
503                                    "8-M.Mainline"),
504         ARMCPUTestParams<uint64_t>("cortex-m35p", "armv8-m.main", "fpv5-sp-d16",
505                                    ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
506                                    "8-M.Mainline"),
507         ARMCPUTestParams<uint64_t>(
508             "cortex-m55", "armv8.1-m.main", "fp-armv8-fullfp16-d16",
509             ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP |
510                 ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16,
511             "8.1-M.Mainline"),
512         ARMCPUTestParams<uint64_t>(
513             "cortex-m85", "armv8.1-m.main", "fp-armv8-fullfp16-d16",
514             ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP |
515                 ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16 | ARM::AEK_PACBTI,
516             "8.1-M.Mainline"),
517         ARMCPUTestParams<uint64_t>(
518             "cortex-m52", "armv8.1-m.main", "fp-armv8-fullfp16-d16",
519             ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP |
520                 ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16 | ARM::AEK_PACBTI,
521             "8.1-M.Mainline"),
522         ARMCPUTestParams<uint64_t>("iwmmxt", "iwmmxt", "none", ARM::AEK_NONE,
523                                    "iwmmxt"),
524         ARMCPUTestParams<uint64_t>("xscale", "xscale", "none", ARM::AEK_NONE,
525                                    "xscale"),
526         ARMCPUTestParams<uint64_t>("swift", "armv7s", "neon-vfpv4",
527                                    ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
528                                        ARM::AEK_DSP,
529                                    "7-S")),
530     ARMCPUTestParams<uint64_t>::PrintToStringParamName);
531 
532 static constexpr unsigned NumARMCPUArchs = 94;
533 
534 TEST(TargetParserTest, testARMCPUArchList) {
535   SmallVector<StringRef, NumARMCPUArchs> List;
536   ARM::fillValidCPUArchList(List);
537 
538   // No list exists for these in this test suite, so ensure all are
539   // valid, and match the expected 'magic' count.
540   EXPECT_EQ(List.size(), NumARMCPUArchs);
541   for (StringRef CPU : List) {
542     EXPECT_NE(ARM::parseCPUArch(CPU), ARM::ArchKind::INVALID);
543   }
544 }
545 
546 TEST(TargetParserTest, testInvalidARMArch) {
547   auto InvalidArchStrings = {"armv", "armv99", "noarm"};
548   for (const char *InvalidArch : InvalidArchStrings)
549     EXPECT_EQ(ARM::parseArch(InvalidArch), ARM::ArchKind::INVALID);
550 }
551 
552 bool testARMArch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,
553                  unsigned ArchAttr) {
554   ARM::ArchKind AK = ARM::parseArch(Arch);
555   bool Result = (AK != ARM::ArchKind::INVALID);
556   Result &= ARM::getDefaultCPU(Arch) == DefaultCPU;
557   Result &= ARM::getSubArch(AK) == SubArch;
558   Result &= (ARM::getArchAttr(AK) == ArchAttr);
559   return Result;
560 }
561 
562 TEST(TargetParserTest, testARMArch) {
563   EXPECT_TRUE(
564       testARMArch("armv4", "strongarm", "v4", ARMBuildAttrs::CPUArch::v4));
565   EXPECT_TRUE(
566       testARMArch("armv4t", "arm7tdmi", "v4t", ARMBuildAttrs::CPUArch::v4T));
567   EXPECT_TRUE(
568       testARMArch("armv5t", "arm10tdmi", "v5", ARMBuildAttrs::CPUArch::v5T));
569   EXPECT_TRUE(
570       testARMArch("armv5te", "arm1022e", "v5e", ARMBuildAttrs::CPUArch::v5TE));
571   EXPECT_TRUE(testARMArch("armv5tej", "arm926ej-s", "v5e",
572                           ARMBuildAttrs::CPUArch::v5TEJ));
573   EXPECT_TRUE(
574       testARMArch("armv6", "arm1136jf-s", "v6", ARMBuildAttrs::CPUArch::v6));
575   EXPECT_TRUE(
576       testARMArch("armv6k", "mpcore", "v6k", ARMBuildAttrs::CPUArch::v6K));
577   EXPECT_TRUE(testARMArch("armv6t2", "arm1156t2-s", "v6t2",
578                           ARMBuildAttrs::CPUArch::v6T2));
579   EXPECT_TRUE(testARMArch("armv6kz", "arm1176jzf-s", "v6kz",
580                           ARMBuildAttrs::CPUArch::v6KZ));
581   EXPECT_TRUE(
582       testARMArch("armv6-m", "cortex-m0", "v6m", ARMBuildAttrs::CPUArch::v6_M));
583   EXPECT_TRUE(
584       testARMArch("armv7-a", "generic", "v7", ARMBuildAttrs::CPUArch::v7));
585   EXPECT_TRUE(
586       testARMArch("armv7ve", "generic", "v7ve", ARMBuildAttrs::CPUArch::v7));
587   EXPECT_TRUE(
588       testARMArch("armv7-r", "cortex-r4", "v7r", ARMBuildAttrs::CPUArch::v7));
589   EXPECT_TRUE(
590       testARMArch("armv7-m", "cortex-m3", "v7m", ARMBuildAttrs::CPUArch::v7));
591   EXPECT_TRUE(testARMArch("armv7e-m", "cortex-m4", "v7em",
592                           ARMBuildAttrs::CPUArch::v7E_M));
593   EXPECT_TRUE(
594       testARMArch("armv8-a", "generic", "v8a", ARMBuildAttrs::CPUArch::v8_A));
595   EXPECT_TRUE(testARMArch("armv8.1-a", "generic", "v8.1a",
596                           ARMBuildAttrs::CPUArch::v8_A));
597   EXPECT_TRUE(testARMArch("armv8.2-a", "generic", "v8.2a",
598                           ARMBuildAttrs::CPUArch::v8_A));
599   EXPECT_TRUE(testARMArch("armv8.3-a", "generic", "v8.3a",
600                           ARMBuildAttrs::CPUArch::v8_A));
601   EXPECT_TRUE(testARMArch("armv8.4-a", "generic", "v8.4a",
602                           ARMBuildAttrs::CPUArch::v8_A));
603   EXPECT_TRUE(testARMArch("armv8.5-a", "generic", "v8.5a",
604                           ARMBuildAttrs::CPUArch::v8_A));
605   EXPECT_TRUE(testARMArch("armv8.6-a", "generic", "v8.6a",
606                           ARMBuildAttrs::CPUArch::v8_A));
607   EXPECT_TRUE(testARMArch("armv8.7-a", "generic", "v8.7a",
608                           ARMBuildAttrs::CPUArch::v8_A));
609   EXPECT_TRUE(testARMArch("armv8.8-a", "generic", "v8.8a",
610                           ARMBuildAttrs::CPUArch::v8_A));
611   EXPECT_TRUE(testARMArch("armv8.9-a", "generic", "v8.9a",
612                           ARMBuildAttrs::CPUArch::v8_A));
613   EXPECT_TRUE(
614       testARMArch("armv9-a", "generic", "v9a", ARMBuildAttrs::CPUArch::v9_A));
615   EXPECT_TRUE(testARMArch("armv9.1-a", "generic", "v9.1a",
616                           ARMBuildAttrs::CPUArch::v9_A));
617   EXPECT_TRUE(testARMArch("armv9.2-a", "generic", "v9.2a",
618                           ARMBuildAttrs::CPUArch::v9_A));
619   EXPECT_TRUE(testARMArch("armv9.3-a", "generic", "v9.3a",
620                           ARMBuildAttrs::CPUArch::v9_A));
621   EXPECT_TRUE(testARMArch("armv9.4-a", "generic", "v9.4a",
622                           ARMBuildAttrs::CPUArch::v9_A));
623   EXPECT_TRUE(testARMArch("armv9.5-a", "generic", "v9.5a",
624                           ARMBuildAttrs::CPUArch::v9_A));
625   EXPECT_TRUE(testARMArch("armv9.6-a", "generic", "v9.6a",
626                           ARMBuildAttrs::CPUArch::v9_A));
627   EXPECT_TRUE(
628       testARMArch("armv8-r", "generic", "v8r", ARMBuildAttrs::CPUArch::v8_R));
629   EXPECT_TRUE(testARMArch("armv8-m.base", "generic", "v8m.base",
630                           ARMBuildAttrs::CPUArch::v8_M_Base));
631   EXPECT_TRUE(testARMArch("armv8-m.main", "generic", "v8m.main",
632                           ARMBuildAttrs::CPUArch::v8_M_Main));
633   EXPECT_TRUE(testARMArch("armv8.1-m.main", "generic", "v8.1m.main",
634                           ARMBuildAttrs::CPUArch::v8_1_M_Main));
635   EXPECT_TRUE(
636       testARMArch("iwmmxt", "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE));
637   EXPECT_TRUE(
638       testARMArch("iwmmxt2", "generic", "", ARMBuildAttrs::CPUArch::v5TE));
639   EXPECT_TRUE(
640       testARMArch("xscale", "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE));
641   EXPECT_TRUE(
642       testARMArch("armv7s", "swift", "v7s", ARMBuildAttrs::CPUArch::v7));
643   EXPECT_TRUE(
644       testARMArch("armv7k", "generic", "v7k", ARMBuildAttrs::CPUArch::v7));
645 }
646 
647 bool testARMExtension(StringRef CPUName, ARM::ArchKind ArchKind,
648                       StringRef ArchExt) {
649   return ARM::getDefaultExtensions(CPUName, ArchKind) &
650          ARM::parseArchExt(ArchExt);
651 }
652 
653 TEST(TargetParserTest, testARMExtension) {
654   EXPECT_FALSE(testARMExtension("strongarm", ARM::ArchKind::INVALID, "dsp"));
655   EXPECT_FALSE(testARMExtension("arm7tdmi", ARM::ArchKind::INVALID, "dsp"));
656   EXPECT_FALSE(testARMExtension("arm10tdmi", ARM::ArchKind::INVALID, "simd"));
657   EXPECT_FALSE(testARMExtension("arm1022e", ARM::ArchKind::INVALID, "simd"));
658   EXPECT_FALSE(testARMExtension("arm926ej-s", ARM::ArchKind::INVALID, "simd"));
659   EXPECT_FALSE(
660       testARMExtension("arm1136jf-s", ARM::ArchKind::INVALID, "crypto"));
661   EXPECT_FALSE(
662       testARMExtension("arm1156t2-s", ARM::ArchKind::INVALID, "crypto"));
663   EXPECT_FALSE(
664       testARMExtension("arm1176jzf-s", ARM::ArchKind::INVALID, "crypto"));
665   EXPECT_FALSE(testARMExtension("cortex-m0", ARM::ArchKind::INVALID, "crypto"));
666   EXPECT_FALSE(testARMExtension("cortex-a8", ARM::ArchKind::INVALID, "crypto"));
667   EXPECT_FALSE(testARMExtension("cortex-r4", ARM::ArchKind::INVALID, "crypto"));
668   EXPECT_FALSE(testARMExtension("cortex-m3", ARM::ArchKind::INVALID, "crypto"));
669   EXPECT_FALSE(testARMExtension("cortex-a53", ARM::ArchKind::INVALID, "ras"));
670   EXPECT_FALSE(testARMExtension("cortex-a53", ARM::ArchKind::INVALID, "fp16"));
671   EXPECT_TRUE(testARMExtension("cortex-a55", ARM::ArchKind::INVALID, "fp16"));
672   EXPECT_FALSE(
673       testARMExtension("cortex-a55", ARM::ArchKind::INVALID, "fp16fml"));
674   EXPECT_TRUE(testARMExtension("cortex-a75", ARM::ArchKind::INVALID, "fp16"));
675   EXPECT_FALSE(
676       testARMExtension("cortex-a75", ARM::ArchKind::INVALID, "fp16fml"));
677   EXPECT_FALSE(testARMExtension("cortex-r52", ARM::ArchKind::INVALID, "ras"));
678   EXPECT_FALSE(
679       testARMExtension("cortex-r52plus", ARM::ArchKind::INVALID, "ras"));
680   EXPECT_FALSE(testARMExtension("iwmmxt", ARM::ArchKind::INVALID, "crc"));
681   EXPECT_FALSE(testARMExtension("xscale", ARM::ArchKind::INVALID, "crc"));
682   EXPECT_FALSE(testARMExtension("swift", ARM::ArchKind::INVALID, "crc"));
683 
684   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV4, "dsp"));
685   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV4T, "dsp"));
686   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5T, "simd"));
687   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5TE, "simd"));
688   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5TEJ, "simd"));
689   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6, "crypto"));
690   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6K, "crypto"));
691   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6T2, "crypto"));
692   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6KZ, "crypto"));
693   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6M, "crypto"));
694   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7A, "crypto"));
695   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7R, "crypto"));
696   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7M, "crypto"));
697   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7EM, "crypto"));
698   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8A, "ras"));
699   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_1A, "ras"));
700   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_2A, "profile"));
701   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_2A, "fp16"));
702   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_2A, "fp16fml"));
703   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_3A, "fp16"));
704   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_3A, "fp16fml"));
705   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_4A, "fp16"));
706   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_4A, "fp16fml"));
707   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8R, "ras"));
708   EXPECT_FALSE(
709       testARMExtension("generic", ARM::ArchKind::ARMV8MBaseline, "crc"));
710   EXPECT_FALSE(
711       testARMExtension("generic", ARM::ArchKind::ARMV8MMainline, "crc"));
712   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::IWMMXT, "crc"));
713   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::IWMMXT2, "crc"));
714   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::XSCALE, "crc"));
715   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7S, "crypto"));
716   EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7K, "crypto"));
717 }
718 
719 TEST(TargetParserTest, ARMFPUVersion) {
720   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
721        FK <= ARM::FPUKind::FK_LAST;
722        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
723     if (FK == ARM::FK_LAST || ARM::getFPUName(FK) == "invalid" ||
724         ARM::getFPUName(FK) == "none" || ARM::getFPUName(FK) == "softvfp")
725       EXPECT_EQ(ARM::FPUVersion::NONE, ARM::getFPUVersion(FK));
726     else
727       EXPECT_NE(ARM::FPUVersion::NONE, ARM::getFPUVersion(FK));
728 }
729 
730 TEST(TargetParserTest, ARMFPUNeonSupportLevel) {
731   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
732        FK <= ARM::FPUKind::FK_LAST;
733        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
734     if (FK == ARM::FK_LAST ||
735         ARM::getFPUName(FK).find("neon") == std::string::npos)
736       EXPECT_EQ(ARM::NeonSupportLevel::None, ARM::getFPUNeonSupportLevel(FK));
737     else
738       EXPECT_NE(ARM::NeonSupportLevel::None, ARM::getFPUNeonSupportLevel(FK));
739 }
740 
741 TEST(TargetParserTest, ARMFPURestriction) {
742   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
743        FK <= ARM::FPUKind::FK_LAST;
744        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) {
745     if (FK == ARM::FK_LAST ||
746         (ARM::getFPUName(FK).find("d16") == std::string::npos &&
747          ARM::getFPUName(FK).find("vfpv3xd") == std::string::npos))
748       EXPECT_EQ(ARM::FPURestriction::None, ARM::getFPURestriction(FK));
749     else
750       EXPECT_NE(ARM::FPURestriction::None, ARM::getFPURestriction(FK));
751   }
752 }
753 
754 TEST(TargetParserTest, ARMExtensionFeatures) {
755   std::map<uint64_t, std::vector<StringRef>> Extensions;
756 
757   for (auto &Ext : ARM::ARCHExtNames) {
758     if (!Ext.Feature.empty() && !Ext.NegFeature.empty())
759       Extensions[Ext.ID] = {Ext.Feature, Ext.NegFeature};
760   }
761 
762   Extensions[ARM::AEK_HWDIVARM] = {"+hwdiv-arm", "-hwdiv-arm"};
763   Extensions[ARM::AEK_HWDIVTHUMB] = {"+hwdiv", "-hwdiv"};
764 
765   std::vector<StringRef> Features;
766 
767   EXPECT_FALSE(ARM::getExtensionFeatures(ARM::AEK_INVALID, Features));
768 
769   for (auto &E : Extensions) {
770     // test +extension
771     Features.clear();
772     ARM::getExtensionFeatures(E.first, Features);
773     EXPECT_TRUE(llvm::is_contained(Features, E.second.at(0)));
774     EXPECT_EQ(Extensions.size(), Features.size());
775 
776     // test -extension
777     Features.clear();
778     ARM::getExtensionFeatures(~E.first, Features);
779     EXPECT_TRUE(llvm::is_contained(Features, E.second.at(1)));
780     EXPECT_EQ(Extensions.size(), Features.size());
781   }
782 }
783 
784 TEST(TargetParserTest, ARMFPUFeatures) {
785   std::vector<StringRef> Features;
786   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
787        FK <= ARM::FPUKind::FK_LAST;
788        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) {
789     if (FK == ARM::FK_INVALID || FK >= ARM::FK_LAST)
790       EXPECT_FALSE(ARM::getFPUFeatures(FK, Features));
791     else
792       EXPECT_TRUE(ARM::getFPUFeatures(FK, Features));
793   }
794 }
795 
796 TEST(TargetParserTest, ARMArchExtFeature) {
797   const char *ArchExt[][4] = {{"crc", "nocrc", "+crc", "-crc"},
798                               {"crypto", "nocrypto", "+crypto", "-crypto"},
799                               {"dsp", "nodsp", "+dsp", "-dsp"},
800                               {"fp", "nofp", nullptr, nullptr},
801                               {"idiv", "noidiv", nullptr, nullptr},
802                               {"mp", "nomp", nullptr, nullptr},
803                               {"simd", "nosimd", nullptr, nullptr},
804                               {"sec", "nosec", nullptr, nullptr},
805                               {"virt", "novirt", nullptr, nullptr},
806                               {"fp16", "nofp16", "+fullfp16", "-fullfp16"},
807                               {"fp16fml", "nofp16fml", "+fp16fml", "-fp16fml"},
808                               {"ras", "noras", "+ras", "-ras"},
809                               {"dotprod", "nodotprod", "+dotprod", "-dotprod"},
810                               {"os", "noos", nullptr, nullptr},
811                               {"iwmmxt", "noiwmmxt", nullptr, nullptr},
812                               {"iwmmxt2", "noiwmmxt2", nullptr, nullptr},
813                               {"maverick", "maverick", nullptr, nullptr},
814                               {"xscale", "noxscale", nullptr, nullptr},
815                               {"sb", "nosb", "+sb", "-sb"},
816                               {"i8mm", "noi8mm", "+i8mm", "-i8mm"},
817                               {"mve", "nomve", "+mve", "-mve"},
818                               {"mve.fp", "nomve.fp", "+mve.fp", "-mve.fp"}};
819 
820   for (unsigned i = 0; i < std::size(ArchExt); i++) {
821     EXPECT_EQ(StringRef(ArchExt[i][2]), ARM::getArchExtFeature(ArchExt[i][0]));
822     EXPECT_EQ(StringRef(ArchExt[i][3]), ARM::getArchExtFeature(ArchExt[i][1]));
823   }
824 }
825 
826 static bool
827 testArchExtDependency(const char *ArchExt,
828                       const std::initializer_list<const char *> &Expected) {
829   std::vector<StringRef> Features;
830   ARM::FPUKind FPUKind;
831 
832   if (!ARM::appendArchExtFeatures("", ARM::ArchKind::ARMV8_1MMainline, ArchExt,
833                                   Features, FPUKind))
834     return false;
835 
836   return llvm::all_of(Expected, [&](StringRef Ext) {
837     return llvm::is_contained(Features, Ext);
838   });
839 }
840 
841 TEST(TargetParserTest, ARMArchExtDependencies) {
842   EXPECT_TRUE(testArchExtDependency("mve", {"+mve", "+dsp"}));
843   EXPECT_TRUE(testArchExtDependency("mve.fp", {"+mve.fp", "+mve", "+dsp"}));
844   EXPECT_TRUE(testArchExtDependency("nodsp", {"-dsp", "-mve", "-mve.fp"}));
845   EXPECT_TRUE(testArchExtDependency("nomve", {"-mve", "-mve.fp"}));
846 }
847 
848 TEST(TargetParserTest, ARMparseHWDiv) {
849   const char *hwdiv[] = {"thumb", "arm", "arm,thumb", "thumb,arm"};
850 
851   for (unsigned i = 0; i < std::size(hwdiv); i++)
852     EXPECT_NE(ARM::AEK_INVALID, ARM::parseHWDiv((StringRef)hwdiv[i]));
853 }
854 
855 TEST(TargetParserTest, ARMparseArchEndianAndISA) {
856   const char *Arch[] = {
857       "v2",        "v2a",    "v3",    "v3m",    "v4",       "v4t",
858       "v5",        "v5t",    "v5e",   "v5te",   "v5tej",    "v6",
859       "v6j",       "v6k",    "v6hl",  "v6t2",   "v6kz",     "v6z",
860       "v6zk",      "v6-m",   "v6m",   "v6sm",   "v6s-m",    "v7-a",
861       "v7",        "v7a",    "v7ve",  "v7hl",   "v7l",      "v7-r",
862       "v7r",       "v7-m",   "v7m",   "v7k",    "v7s",      "v7e-m",
863       "v7em",      "v8-a",   "v8",    "v8a",    "v8l",      "v8.1-a",
864       "v8.1a",     "v8.2-a", "v8.2a", "v8.3-a", "v8.3a",    "v8.4-a",
865       "v8.4a",     "v8.5-a", "v8.5a", "v8.6-a", "v8.6a",    "v8.7-a",
866       "v8.7a",     "v8.8-a", "v8.8a", "v8-r",   "v8m.base", "v8m.main",
867       "v8.1m.main"};
868 
869   for (unsigned i = 0; i < std::size(Arch); i++) {
870     std::string arm_1 = "armeb" + (std::string)(Arch[i]);
871     std::string arm_2 = "arm" + (std::string)(Arch[i]) + "eb";
872     std::string arm_3 = "arm" + (std::string)(Arch[i]);
873     std::string thumb_1 = "thumbeb" + (std::string)(Arch[i]);
874     std::string thumb_2 = "thumb" + (std::string)(Arch[i]) + "eb";
875     std::string thumb_3 = "thumb" + (std::string)(Arch[i]);
876 
877     EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(arm_1));
878     EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(arm_2));
879     EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian(arm_3));
880 
881     EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_1));
882     EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_2));
883     EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_3));
884     if (i >= 4) {
885       EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(thumb_1));
886       EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(thumb_2));
887       EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian(thumb_3));
888 
889       EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_1));
890       EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_2));
891       EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_3));
892     }
893   }
894 
895   EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian("aarch64"));
896   EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian("arm64_32"));
897   EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian("aarch64_be"));
898 
899   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("aarch64"));
900   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("aarch64_be"));
901   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("arm64"));
902   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("arm64_be"));
903   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("arm64_32"));
904   EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("aarch64_32"));
905 }
906 
907 TEST(TargetParserTest, ARMparseArchProfile) {
908   for (unsigned i = 0; i < std::size(ARMArch); i++) {
909     switch (ARM::parseArch(ARMArch[i])) {
910     case ARM::ArchKind::ARMV6M:
911     case ARM::ArchKind::ARMV7M:
912     case ARM::ArchKind::ARMV7EM:
913     case ARM::ArchKind::ARMV8MMainline:
914     case ARM::ArchKind::ARMV8MBaseline:
915     case ARM::ArchKind::ARMV8_1MMainline:
916       EXPECT_EQ(ARM::ProfileKind::M, ARM::parseArchProfile(ARMArch[i]));
917       break;
918     case ARM::ArchKind::ARMV7R:
919     case ARM::ArchKind::ARMV8R:
920       EXPECT_EQ(ARM::ProfileKind::R, ARM::parseArchProfile(ARMArch[i]));
921       break;
922     case ARM::ArchKind::ARMV7A:
923     case ARM::ArchKind::ARMV7VE:
924     case ARM::ArchKind::ARMV7K:
925     case ARM::ArchKind::ARMV8A:
926     case ARM::ArchKind::ARMV8_1A:
927     case ARM::ArchKind::ARMV8_2A:
928     case ARM::ArchKind::ARMV8_3A:
929     case ARM::ArchKind::ARMV8_4A:
930     case ARM::ArchKind::ARMV8_5A:
931     case ARM::ArchKind::ARMV8_6A:
932     case ARM::ArchKind::ARMV8_7A:
933     case ARM::ArchKind::ARMV8_8A:
934     case ARM::ArchKind::ARMV8_9A:
935     case ARM::ArchKind::ARMV9A:
936     case ARM::ArchKind::ARMV9_1A:
937     case ARM::ArchKind::ARMV9_2A:
938     case ARM::ArchKind::ARMV9_3A:
939     case ARM::ArchKind::ARMV9_4A:
940     case ARM::ArchKind::ARMV9_5A:
941     case ARM::ArchKind::ARMV9_6A:
942       EXPECT_EQ(ARM::ProfileKind::A, ARM::parseArchProfile(ARMArch[i]));
943       break;
944     default:
945       EXPECT_EQ(ARM::ProfileKind::INVALID, ARM::parseArchProfile(ARMArch[i]));
946       break;
947     }
948   }
949 }
950 
951 TEST(TargetParserTest, ARMparseArchVersion) {
952   for (unsigned i = 0; i < std::size(ARMArch); i++)
953     if (((std::string)ARMArch[i]).substr(0, 4) == "armv")
954       EXPECT_EQ((ARMArch[i][4] - 48u), ARM::parseArchVersion(ARMArch[i]));
955     else
956       EXPECT_EQ(5u, ARM::parseArchVersion(ARMArch[i]));
957 }
958 
959 TEST(TargetParserTest, getARMCPUForArch) {
960   // Platform specific defaults.
961   {
962     llvm::Triple Triple("arm--nacl");
963     EXPECT_EQ("cortex-a8", ARM::getARMCPUForArch(Triple));
964   }
965   {
966     llvm::Triple Triple("arm--openbsd");
967     EXPECT_EQ("cortex-a8", ARM::getARMCPUForArch(Triple));
968   }
969   {
970     llvm::Triple Triple("armv6-unknown-freebsd");
971     EXPECT_EQ("arm1176jzf-s", ARM::getARMCPUForArch(Triple));
972   }
973   {
974     llvm::Triple Triple("thumbv6-unknown-freebsd");
975     EXPECT_EQ("arm1176jzf-s", ARM::getARMCPUForArch(Triple));
976   }
977   {
978     llvm::Triple Triple("armebv6-unknown-freebsd");
979     EXPECT_EQ("arm1176jzf-s", ARM::getARMCPUForArch(Triple));
980   }
981   {
982     llvm::Triple Triple("arm--win32");
983     EXPECT_EQ("cortex-a9", ARM::getARMCPUForArch(Triple));
984     EXPECT_EQ("generic", ARM::getARMCPUForArch(Triple, "armv8-a"));
985   }
986   // Some alternative architectures
987   {
988     llvm::Triple Triple("armv7k-apple-ios9");
989     EXPECT_EQ("cortex-a7", ARM::getARMCPUForArch(Triple));
990   }
991   {
992     llvm::Triple Triple("armv7k-apple-watchos3");
993     EXPECT_EQ("cortex-a7", ARM::getARMCPUForArch(Triple));
994   }
995   {
996     llvm::Triple Triple("armv7k-apple-tvos9");
997     EXPECT_EQ("cortex-a7", ARM::getARMCPUForArch(Triple));
998   }
999   // armeb is permitted, but armebeb is not
1000   {
1001     llvm::Triple Triple("armeb-none-eabi");
1002     EXPECT_EQ("arm7tdmi", ARM::getARMCPUForArch(Triple));
1003   }
1004   {
1005     llvm::Triple Triple("armebeb-none-eabi");
1006     EXPECT_EQ("", ARM::getARMCPUForArch(Triple));
1007   }
1008   {
1009     llvm::Triple Triple("armebv6eb-none-eabi");
1010     EXPECT_EQ("", ARM::getARMCPUForArch(Triple));
1011   }
1012   // xscaleeb is permitted, but armebxscale is not
1013   {
1014     llvm::Triple Triple("xscaleeb-none-eabi");
1015     EXPECT_EQ("xscale", ARM::getARMCPUForArch(Triple));
1016   }
1017   {
1018     llvm::Triple Triple("armebxscale-none-eabi");
1019     EXPECT_EQ("", ARM::getARMCPUForArch(Triple));
1020   }
1021 }
1022 
1023 TEST(TargetParserTest, ARMPrintSupportedExtensions) {
1024   std::string expected =
1025       "All available -march extensions for ARM\n\n"
1026       "    Name                Description\n"
1027       "    crc                 This is a long dummy description\n"
1028       "    crypto\n"
1029       "    sha2\n";
1030 
1031   StringMap<StringRef> DummyMap;
1032   DummyMap["crc"] = "This is a long dummy description";
1033 
1034   outs().flush();
1035   testing::internal::CaptureStdout();
1036   ARM::PrintSupportedExtensions(DummyMap);
1037   outs().flush();
1038   std::string captured = testing::internal::GetCapturedStdout();
1039 
1040   // Check that the start of the output is as expected.
1041   EXPECT_EQ(0ULL, captured.find(expected));
1042 
1043   // Should not include "none" or "invalid".
1044   EXPECT_EQ(std::string::npos, captured.find("none"));
1045   EXPECT_EQ(std::string::npos, captured.find("invalid"));
1046   // Should not include anything that lacks a feature name. Checking a few here
1047   // but not all as if one is hidden correctly the rest should be.
1048   EXPECT_EQ(std::string::npos, captured.find("simd"));
1049   EXPECT_EQ(std::string::npos, captured.find("maverick"));
1050   EXPECT_EQ(std::string::npos, captured.find("xscale"));
1051 }
1052 
1053 struct AArch64CPUTestParams
1054     : public ARMCPUTestParams<AArch64::ExtensionBitset> {
1055   AArch64CPUTestParams(StringRef CPUName, StringRef ExpectedArch)
1056       : ARMCPUTestParams<AArch64::ExtensionBitset>(CPUName, ExpectedArch,
1057                                                    /*ignored*/ "", {},
1058                                                    /*ignored*/ "") {}
1059   /// Print a gtest-compatible facsimile of the CPUName, to make the test's name
1060   /// human-readable.
1061   ///
1062   /// https://github.com/google/googletest/blob/main/docs/advanced.md#specifying-names-for-value-parameterized-test-parameters
1063   static std::string PrintToStringParamName(
1064       const testing::TestParamInfo<AArch64CPUTestParams> &Info) {
1065     std::string Name = Info.param.CPUName.str();
1066     for (char &C : Name)
1067       if (!std::isalnum(C))
1068         C = '_';
1069     return Name;
1070   }
1071 };
1072 
1073 class AArch64CPUTestFixture
1074     : public ::testing::TestWithParam<AArch64CPUTestParams> {};
1075 
1076 TEST_P(AArch64CPUTestFixture, testAArch64CPU) {
1077   auto params = GetParam();
1078 
1079   const std::optional<AArch64::CpuInfo> Cpu = AArch64::parseCpu(params.CPUName);
1080   EXPECT_TRUE(Cpu);
1081   EXPECT_EQ(params.ExpectedArch, Cpu->Arch.Name);
1082 }
1083 
1084 INSTANTIATE_TEST_SUITE_P(
1085     AArch64CPUTests, AArch64CPUTestFixture,
1086     ::testing::Values(AArch64CPUTestParams("cortex-a34", "armv8-a"),
1087                       AArch64CPUTestParams("cortex-a35", "armv8-a"),
1088                       AArch64CPUTestParams("cortex-a53", "armv8-a"),
1089                       AArch64CPUTestParams("cortex-a55", "armv8.2-a"),
1090                       AArch64CPUTestParams("cortex-a510", "armv9-a"),
1091                       AArch64CPUTestParams("cortex-a520", "armv9.2-a"),
1092                       AArch64CPUTestParams("cortex-a520ae", "armv9.2-a"),
1093                       AArch64CPUTestParams("cortex-a57", "armv8-a"),
1094                       AArch64CPUTestParams("cortex-a65", "armv8.2-a"),
1095                       AArch64CPUTestParams("cortex-a65ae", "armv8.2-a"),
1096                       AArch64CPUTestParams("cortex-a72", "armv8-a"),
1097                       AArch64CPUTestParams("cortex-a73", "armv8-a"),
1098                       AArch64CPUTestParams("cortex-a75", "armv8.2-a"),
1099                       AArch64CPUTestParams("cortex-a76", "armv8.2-a"),
1100                       AArch64CPUTestParams("cortex-a76ae", "armv8.2-a"),
1101                       AArch64CPUTestParams("cortex-a77", "armv8.2-a"),
1102                       AArch64CPUTestParams("cortex-a78", "armv8.2-a"),
1103                       AArch64CPUTestParams("cortex-a78ae", "armv8.2-a"),
1104                       AArch64CPUTestParams("cortex-a78c", "armv8.2-a"),
1105                       AArch64CPUTestParams("cortex-a710", "armv9-a"),
1106                       AArch64CPUTestParams("cortex-a715", "armv9-a"),
1107                       AArch64CPUTestParams("cortex-a720", "armv9.2-a"),
1108                       AArch64CPUTestParams("cortex-a720ae", "armv9.2-a"),
1109                       AArch64CPUTestParams("cortex-a725", "armv9.2-a"),
1110                       AArch64CPUTestParams("neoverse-v1", "armv8.4-a"),
1111                       AArch64CPUTestParams("neoverse-v2", "armv9-a"),
1112                       AArch64CPUTestParams("neoverse-v3", "armv9.2-a"),
1113                       AArch64CPUTestParams("neoverse-v3ae", "armv9.2-a"),
1114                       AArch64CPUTestParams("cortex-r82", "armv8-r"),
1115                       AArch64CPUTestParams("cortex-r82ae", "armv8-r"),
1116                       AArch64CPUTestParams("cortex-x1", "armv8.2-a"),
1117                       AArch64CPUTestParams("cortex-x1c", "armv8.2-a"),
1118                       AArch64CPUTestParams("cortex-x2", "armv9-a"),
1119                       AArch64CPUTestParams("cortex-x3", "armv9-a"),
1120                       AArch64CPUTestParams("cortex-x4", "armv9.2-a"),
1121                       AArch64CPUTestParams("cortex-x925", "armv9.2-a"),
1122                       AArch64CPUTestParams("cyclone", "armv8-a"),
1123                       AArch64CPUTestParams("apple-a7", "armv8-a"),
1124                       AArch64CPUTestParams("apple-a8", "armv8-a"),
1125                       AArch64CPUTestParams("apple-a9", "armv8-a"),
1126                       AArch64CPUTestParams("apple-a10", "armv8-a"),
1127                       AArch64CPUTestParams("apple-a11", "armv8.2-a"),
1128                       AArch64CPUTestParams("apple-a12", "armv8.3-a"),
1129                       AArch64CPUTestParams("apple-s4", "armv8.3-a"),
1130                       AArch64CPUTestParams("apple-s5", "armv8.3-a"),
1131                       AArch64CPUTestParams("apple-a13", "armv8.4-a"),
1132                       AArch64CPUTestParams("apple-a14", "armv8.4-a"),
1133                       AArch64CPUTestParams("apple-m1", "armv8.4-a"),
1134                       AArch64CPUTestParams("apple-a15", "armv8.6-a"),
1135                       AArch64CPUTestParams("apple-m2", "armv8.6-a"),
1136                       AArch64CPUTestParams("apple-a16", "armv8.6-a"),
1137                       AArch64CPUTestParams("apple-m3", "armv8.6-a"),
1138                       AArch64CPUTestParams("apple-a17", "armv8.6-a"),
1139                       AArch64CPUTestParams("apple-m4", "armv8.7-a"),
1140                       AArch64CPUTestParams("exynos-m3", "armv8-a"),
1141                       AArch64CPUTestParams("exynos-m4", "armv8.2-a"),
1142                       AArch64CPUTestParams("exynos-m5", "armv8.2-a"),
1143                       AArch64CPUTestParams("falkor", "armv8-a"),
1144                       AArch64CPUTestParams("kryo", "armv8-a"),
1145                       AArch64CPUTestParams("neoverse-e1", "armv8.2-a"),
1146                       AArch64CPUTestParams("neoverse-n1", "armv8.2-a"),
1147                       AArch64CPUTestParams("neoverse-n2", "armv9-a"),
1148                       AArch64CPUTestParams("neoverse-n3", "armv9.2-a"),
1149                       AArch64CPUTestParams("ampere1", "armv8.6-a"),
1150                       AArch64CPUTestParams("ampere1a", "armv8.6-a"),
1151                       AArch64CPUTestParams("ampere1b", "armv8.7-a"),
1152                       AArch64CPUTestParams("neoverse-512tvb", "armv8.4-a"),
1153                       AArch64CPUTestParams("thunderx2t99", "armv8.1-a"),
1154                       AArch64CPUTestParams("thunderx3t110", "armv8.3-a"),
1155                       AArch64CPUTestParams("thunderx", "armv8-a"),
1156                       AArch64CPUTestParams("thunderxt81", "armv8-a"),
1157                       AArch64CPUTestParams("thunderxt83", "armv8-a"),
1158                       AArch64CPUTestParams("thunderxt88", "armv8-a"),
1159                       AArch64CPUTestParams("tsv110", "armv8.2-a"),
1160                       AArch64CPUTestParams("a64fx", "armv8.2-a"),
1161                       AArch64CPUTestParams("fujitsu-monaka", "armv9.3-a"),
1162                       AArch64CPUTestParams("carmel", "armv8.2-a"),
1163                       AArch64CPUTestParams("saphira", "armv8.4-a"),
1164                       AArch64CPUTestParams("oryon-1", "armv8.6-a")),
1165     AArch64CPUTestParams::PrintToStringParamName);
1166 
1167 // Note: number of CPUs includes aliases.
1168 static constexpr unsigned NumAArch64CPUArchs = 82;
1169 
1170 TEST(TargetParserTest, testAArch64CPUArchList) {
1171   SmallVector<StringRef, NumAArch64CPUArchs> List;
1172   AArch64::fillValidCPUArchList(List);
1173 
1174   // No list exists for these in this test suite, so ensure all are
1175   // valid, and match the expected 'magic' count.
1176   EXPECT_EQ(List.size(), NumAArch64CPUArchs);
1177   for (StringRef CPU : List) {
1178     EXPECT_TRUE(AArch64::parseCpu(CPU));
1179   }
1180 }
1181 
1182 bool testAArch64Arch(StringRef Arch) {
1183   const AArch64::ArchInfo *AI = AArch64::parseArch(Arch);
1184   return AI != nullptr;
1185 }
1186 
1187 TEST(TargetParserTest, testAArch64Arch) {
1188   EXPECT_TRUE(testAArch64Arch("armv8-a"));
1189   EXPECT_TRUE(testAArch64Arch("armv8.1-a"));
1190   EXPECT_TRUE(testAArch64Arch("armv8.2-a"));
1191   EXPECT_TRUE(testAArch64Arch("armv8.3-a"));
1192   EXPECT_TRUE(testAArch64Arch("armv8.4-a"));
1193   EXPECT_TRUE(testAArch64Arch("armv8.5-a"));
1194   EXPECT_TRUE(testAArch64Arch("armv8.6-a"));
1195   EXPECT_TRUE(testAArch64Arch("armv8.7-a"));
1196   EXPECT_TRUE(testAArch64Arch("armv8.8-a"));
1197   EXPECT_TRUE(testAArch64Arch("armv8.9-a"));
1198   EXPECT_TRUE(testAArch64Arch("armv9-a"));
1199   EXPECT_TRUE(testAArch64Arch("armv9.1-a"));
1200   EXPECT_TRUE(testAArch64Arch("armv9.2-a"));
1201   EXPECT_TRUE(testAArch64Arch("armv9.3-a"));
1202   EXPECT_TRUE(testAArch64Arch("armv9.4-a"));
1203   EXPECT_TRUE(testAArch64Arch("armv9.5-a"));
1204   EXPECT_TRUE(testAArch64Arch("armv9.6-a"));
1205 }
1206 
1207 bool testAArch64Extension(StringRef CPUName, StringRef ArchExt) {
1208   std::optional<AArch64::ExtensionInfo> Extension =
1209       AArch64::parseArchExtension(ArchExt);
1210   if (!Extension)
1211     return false;
1212   std::optional<AArch64::CpuInfo> CpuInfo = AArch64::parseCpu(CPUName);
1213   return CpuInfo->getImpliedExtensions().test(Extension->ID);
1214 }
1215 
1216 bool testAArch64Extension(const AArch64::ArchInfo &AI, StringRef ArchExt) {
1217   std::optional<AArch64::ExtensionInfo> Extension =
1218       AArch64::parseArchExtension(ArchExt);
1219   if (!Extension)
1220     return false;
1221   return AI.DefaultExts.test(Extension->ID);
1222 }
1223 
1224 TEST(TargetParserTest, testAArch64Extension) {
1225   EXPECT_FALSE(testAArch64Extension("cortex-a34", "ras"));
1226   EXPECT_FALSE(testAArch64Extension("cortex-a35", "ras"));
1227   EXPECT_FALSE(testAArch64Extension("cortex-a53", "ras"));
1228   EXPECT_TRUE(testAArch64Extension("cortex-a55", "ras"));
1229   EXPECT_TRUE(testAArch64Extension("cortex-a55", "fp16"));
1230   EXPECT_FALSE(testAArch64Extension("cortex-a55", "fp16fml"));
1231   EXPECT_TRUE(testAArch64Extension("cortex-a55", "dotprod"));
1232   EXPECT_FALSE(testAArch64Extension("cortex-a57", "ras"));
1233   EXPECT_FALSE(testAArch64Extension("cortex-a72", "ras"));
1234   EXPECT_FALSE(testAArch64Extension("cortex-a73", "ras"));
1235   EXPECT_TRUE(testAArch64Extension("cortex-a75", "ras"));
1236   EXPECT_TRUE(testAArch64Extension("cortex-a75", "fp16"));
1237   EXPECT_FALSE(testAArch64Extension("cortex-a75", "fp16fml"));
1238   EXPECT_TRUE(testAArch64Extension("cortex-a75", "dotprod"));
1239   EXPECT_TRUE(testAArch64Extension("cortex-r82", "ras"));
1240   EXPECT_TRUE(testAArch64Extension("cortex-r82", "fp16"));
1241   EXPECT_TRUE(testAArch64Extension("cortex-r82", "fp16fml"));
1242   EXPECT_TRUE(testAArch64Extension("cortex-r82", "dotprod"));
1243   EXPECT_TRUE(testAArch64Extension("cortex-r82", "lse"));
1244   EXPECT_FALSE(testAArch64Extension("cyclone", "ras"));
1245   EXPECT_FALSE(testAArch64Extension("exynos-m3", "ras"));
1246   EXPECT_TRUE(testAArch64Extension("exynos-m4", "dotprod"));
1247   EXPECT_TRUE(testAArch64Extension("exynos-m4", "fp16"));
1248   EXPECT_TRUE(testAArch64Extension("exynos-m4", "lse"));
1249   EXPECT_TRUE(testAArch64Extension("exynos-m4", "ras"));
1250   EXPECT_TRUE(testAArch64Extension("exynos-m4", "rdm"));
1251   EXPECT_TRUE(testAArch64Extension("exynos-m5", "dotprod"));
1252   EXPECT_TRUE(testAArch64Extension("exynos-m5", "fp16"));
1253   EXPECT_TRUE(testAArch64Extension("exynos-m5", "lse"));
1254   EXPECT_TRUE(testAArch64Extension("exynos-m5", "ras"));
1255   EXPECT_TRUE(testAArch64Extension("exynos-m5", "rdm"));
1256   EXPECT_TRUE(testAArch64Extension("falkor", "rdm"));
1257   EXPECT_FALSE(testAArch64Extension("kryo", "ras"));
1258   EXPECT_TRUE(testAArch64Extension("saphira", "crc"));
1259   EXPECT_TRUE(testAArch64Extension("saphira", "lse"));
1260   EXPECT_TRUE(testAArch64Extension("saphira", "rdm"));
1261   EXPECT_TRUE(testAArch64Extension("saphira", "ras"));
1262   EXPECT_TRUE(testAArch64Extension("saphira", "rcpc"));
1263   EXPECT_TRUE(testAArch64Extension("saphira", "profile"));
1264   EXPECT_FALSE(testAArch64Extension("saphira", "fp16"));
1265   EXPECT_FALSE(testAArch64Extension("thunderx2t99", "ras"));
1266   EXPECT_FALSE(testAArch64Extension("thunderx", "lse"));
1267   EXPECT_FALSE(testAArch64Extension("thunderxt81", "lse"));
1268   EXPECT_FALSE(testAArch64Extension("thunderxt83", "lse"));
1269   EXPECT_FALSE(testAArch64Extension("thunderxt88", "lse"));
1270   EXPECT_TRUE(testAArch64Extension("tsv110", "aes"));
1271   EXPECT_TRUE(testAArch64Extension("tsv110", "sha2"));
1272   EXPECT_FALSE(testAArch64Extension("tsv110", "sha3"));
1273   EXPECT_FALSE(testAArch64Extension("tsv110", "sm4"));
1274   EXPECT_TRUE(testAArch64Extension("tsv110", "ras"));
1275   EXPECT_TRUE(testAArch64Extension("tsv110", "profile"));
1276   EXPECT_TRUE(testAArch64Extension("tsv110", "fp16"));
1277   EXPECT_TRUE(testAArch64Extension("tsv110", "fp16fml"));
1278   EXPECT_TRUE(testAArch64Extension("tsv110", "dotprod"));
1279   EXPECT_TRUE(testAArch64Extension("tsv110", "jscvt"));
1280   EXPECT_TRUE(testAArch64Extension("tsv110", "fcma"));
1281   EXPECT_TRUE(testAArch64Extension("a64fx", "fp16"));
1282   EXPECT_TRUE(testAArch64Extension("a64fx", "sve"));
1283   EXPECT_FALSE(testAArch64Extension("a64fx", "sve2"));
1284   EXPECT_TRUE(testAArch64Extension("carmel", "aes"));
1285   EXPECT_TRUE(testAArch64Extension("carmel", "sha2"));
1286   EXPECT_TRUE(testAArch64Extension("carmel", "fp16"));
1287 
1288   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8A, "ras"));
1289   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_1A, "ras"));
1290   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "profile"));
1291   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "fp16"));
1292   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_2A, "fp16fml"));
1293   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_3A, "fp16"));
1294   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_3A, "fp16fml"));
1295   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16"));
1296   EXPECT_FALSE(testAArch64Extension(AArch64::ARMV8_4A, "fp16fml"));
1297 }
1298 
1299 TEST(TargetParserTest, AArch64ExtensionFeatures) {
1300   std::vector<uint64_t> Extensions = {
1301       AArch64::AEK_CRC,          AArch64::AEK_LSE,
1302       AArch64::AEK_RDM,          AArch64::AEK_CRYPTO,
1303       AArch64::AEK_SM4,          AArch64::AEK_SHA3,
1304       AArch64::AEK_SHA2,         AArch64::AEK_AES,
1305       AArch64::AEK_DOTPROD,      AArch64::AEK_FP,
1306       AArch64::AEK_SIMD,         AArch64::AEK_FP16,
1307       AArch64::AEK_FP16FML,      AArch64::AEK_PROFILE,
1308       AArch64::AEK_RAS,          AArch64::AEK_SVE,
1309       AArch64::AEK_SVE2,         AArch64::AEK_SVE2AES,
1310       AArch64::AEK_SVE2SM4,      AArch64::AEK_SVE2SHA3,
1311       AArch64::AEK_SVE2BITPERM,  AArch64::AEK_RCPC,
1312       AArch64::AEK_RAND,         AArch64::AEK_MTE,
1313       AArch64::AEK_SSBS,         AArch64::AEK_SB,
1314       AArch64::AEK_PREDRES,      AArch64::AEK_BF16,
1315       AArch64::AEK_I8MM,         AArch64::AEK_F32MM,
1316       AArch64::AEK_F64MM,        AArch64::AEK_TME,
1317       AArch64::AEK_LS64,         AArch64::AEK_BRBE,
1318       AArch64::AEK_PAUTH,        AArch64::AEK_FLAGM,
1319       AArch64::AEK_SME,          AArch64::AEK_SMEF64F64,
1320       AArch64::AEK_SMEI16I64,    AArch64::AEK_SME2,
1321       AArch64::AEK_HBC,          AArch64::AEK_MOPS,
1322       AArch64::AEK_PERFMON,      AArch64::AEK_SVE2P1,
1323       AArch64::AEK_SME2P1,       AArch64::AEK_SMEB16B16,
1324       AArch64::AEK_SMEF16F16,    AArch64::AEK_CSSC,
1325       AArch64::AEK_RCPC3,        AArch64::AEK_THE,
1326       AArch64::AEK_D128,         AArch64::AEK_LSE128,
1327       AArch64::AEK_SPECRES2,     AArch64::AEK_RASV2,
1328       AArch64::AEK_ITE,          AArch64::AEK_GCS,
1329       AArch64::AEK_FAMINMAX,     AArch64::AEK_FP8FMA,
1330       AArch64::AEK_SSVE_FP8FMA,  AArch64::AEK_FP8DOT2,
1331       AArch64::AEK_SSVE_FP8DOT2, AArch64::AEK_FP8DOT4,
1332       AArch64::AEK_SSVE_FP8DOT4, AArch64::AEK_LUT,
1333       AArch64::AEK_SME_LUTV2,    AArch64::AEK_SMEF8F16,
1334       AArch64::AEK_SMEF8F32,     AArch64::AEK_SMEFA64,
1335       AArch64::AEK_CPA,          AArch64::AEK_PAUTHLR,
1336       AArch64::AEK_TLBIW,        AArch64::AEK_JSCVT,
1337       AArch64::AEK_FCMA,         AArch64::AEK_FP8,
1338       AArch64::AEK_SVEB16B16,    AArch64::AEK_SVE2P2,
1339       AArch64::AEK_SME2P2,       AArch64::AEK_SVE_BFSCALE,
1340       AArch64::AEK_SVE_F16F32MM, AArch64::AEK_SVE_AES2,
1341       AArch64::AEK_SSVE_AES,     AArch64::AEK_F8F32MM,
1342       AArch64::AEK_F8F16MM,      AArch64::AEK_LSFE,
1343       AArch64::AEK_FPRCVT,       AArch64::AEK_CMPBR,
1344       AArch64::AEK_LSUI,         AArch64::AEK_OCCMO,
1345       AArch64::AEK_PCDPHINT,     AArch64::AEK_POPS,
1346       AArch64::AEK_SVEAES,       AArch64::AEK_SME_MOP4,
1347       AArch64::AEK_SME_TMOP,     AArch64::AEK_SVEBITPERM,
1348       AArch64::AEK_SSVE_BITPERM,
1349   };
1350 
1351   std::vector<StringRef> Features;
1352 
1353   AArch64::ExtensionBitset ExtVal;
1354   for (auto Ext : Extensions)
1355     ExtVal.set(Ext);
1356 
1357   // Test an empty set of features.
1358   EXPECT_TRUE(AArch64::getExtensionFeatures({}, Features));
1359   EXPECT_TRUE(Features.size() == 0);
1360 
1361   AArch64::getExtensionFeatures(ExtVal, Features);
1362   EXPECT_EQ(Extensions.size(), Features.size());
1363 
1364   EXPECT_TRUE(llvm::is_contained(Features, "+crc"));
1365   EXPECT_TRUE(llvm::is_contained(Features, "+lse"));
1366   EXPECT_TRUE(llvm::is_contained(Features, "+rdm"));
1367   EXPECT_TRUE(llvm::is_contained(Features, "+crypto"));
1368   EXPECT_TRUE(llvm::is_contained(Features, "+sm4"));
1369   EXPECT_TRUE(llvm::is_contained(Features, "+sha3"));
1370   EXPECT_TRUE(llvm::is_contained(Features, "+sha2"));
1371   EXPECT_TRUE(llvm::is_contained(Features, "+aes"));
1372   EXPECT_TRUE(llvm::is_contained(Features, "+dotprod"));
1373   EXPECT_TRUE(llvm::is_contained(Features, "+fp-armv8"));
1374   EXPECT_TRUE(llvm::is_contained(Features, "+neon"));
1375   EXPECT_TRUE(llvm::is_contained(Features, "+fullfp16"));
1376   EXPECT_TRUE(llvm::is_contained(Features, "+fp16fml"));
1377   EXPECT_TRUE(llvm::is_contained(Features, "+spe"));
1378   EXPECT_TRUE(llvm::is_contained(Features, "+ras"));
1379   EXPECT_TRUE(llvm::is_contained(Features, "+sve"));
1380   EXPECT_TRUE(llvm::is_contained(Features, "+sve-b16b16"));
1381   EXPECT_TRUE(llvm::is_contained(Features, "+sve-bfscale"));
1382   EXPECT_TRUE(llvm::is_contained(Features, "+sve-f16f32mm"));
1383   EXPECT_TRUE(llvm::is_contained(Features, "+sve2"));
1384   EXPECT_TRUE(llvm::is_contained(Features, "+sve-aes"));
1385   EXPECT_TRUE(llvm::is_contained(Features, "+sve2-aes"));
1386   EXPECT_TRUE(llvm::is_contained(Features, "+sve2-sm4"));
1387   EXPECT_TRUE(llvm::is_contained(Features, "+sve2-sha3"));
1388   EXPECT_TRUE(llvm::is_contained(Features, "+sve-bitperm"));
1389   EXPECT_TRUE(llvm::is_contained(Features, "+sve2-bitperm"));
1390   EXPECT_TRUE(llvm::is_contained(Features, "+ssve-bitperm"));
1391   EXPECT_TRUE(llvm::is_contained(Features, "+sve-aes2"));
1392   EXPECT_TRUE(llvm::is_contained(Features, "+ssve-aes"));
1393   EXPECT_TRUE(llvm::is_contained(Features, "+sve2p1"));
1394   EXPECT_TRUE(llvm::is_contained(Features, "+sve2p2"));
1395   EXPECT_TRUE(llvm::is_contained(Features, "+rcpc"));
1396   EXPECT_TRUE(llvm::is_contained(Features, "+rand"));
1397   EXPECT_TRUE(llvm::is_contained(Features, "+mte"));
1398   EXPECT_TRUE(llvm::is_contained(Features, "+ssbs"));
1399   EXPECT_TRUE(llvm::is_contained(Features, "+sb"));
1400   EXPECT_TRUE(llvm::is_contained(Features, "+predres"));
1401   EXPECT_TRUE(llvm::is_contained(Features, "+bf16"));
1402   EXPECT_TRUE(llvm::is_contained(Features, "+i8mm"));
1403   EXPECT_TRUE(llvm::is_contained(Features, "+f32mm"));
1404   EXPECT_TRUE(llvm::is_contained(Features, "+f64mm"));
1405   EXPECT_TRUE(llvm::is_contained(Features, "+tme"));
1406   EXPECT_TRUE(llvm::is_contained(Features, "+ls64"));
1407   EXPECT_TRUE(llvm::is_contained(Features, "+brbe"));
1408   EXPECT_TRUE(llvm::is_contained(Features, "+pauth"));
1409   EXPECT_TRUE(llvm::is_contained(Features, "+flagm"));
1410   EXPECT_TRUE(llvm::is_contained(Features, "+sme"));
1411   EXPECT_TRUE(llvm::is_contained(Features, "+sme-f64f64"));
1412   EXPECT_TRUE(llvm::is_contained(Features, "+sme-i16i64"));
1413   EXPECT_TRUE(llvm::is_contained(Features, "+sme-f16f16"));
1414   EXPECT_TRUE(llvm::is_contained(Features, "+sme2"));
1415   EXPECT_TRUE(llvm::is_contained(Features, "+sme-b16b16"));
1416   EXPECT_TRUE(llvm::is_contained(Features, "+sme2p1"));
1417   EXPECT_TRUE(llvm::is_contained(Features, "+sme2p2"));
1418   EXPECT_TRUE(llvm::is_contained(Features, "+hbc"));
1419   EXPECT_TRUE(llvm::is_contained(Features, "+mops"));
1420   EXPECT_TRUE(llvm::is_contained(Features, "+perfmon"));
1421   EXPECT_TRUE(llvm::is_contained(Features, "+cssc"));
1422   EXPECT_TRUE(llvm::is_contained(Features, "+rcpc3"));
1423   EXPECT_TRUE(llvm::is_contained(Features, "+the"));
1424   EXPECT_TRUE(llvm::is_contained(Features, "+d128"));
1425   EXPECT_TRUE(llvm::is_contained(Features, "+lse128"));
1426   EXPECT_TRUE(llvm::is_contained(Features, "+specres2"));
1427   EXPECT_TRUE(llvm::is_contained(Features, "+ite"));
1428   EXPECT_TRUE(llvm::is_contained(Features, "+gcs"));
1429   EXPECT_TRUE(llvm::is_contained(Features, "+fp8"));
1430   EXPECT_TRUE(llvm::is_contained(Features, "+faminmax"));
1431   EXPECT_TRUE(llvm::is_contained(Features, "+fp8fma"));
1432   EXPECT_TRUE(llvm::is_contained(Features, "+ssve-fp8fma"));
1433   EXPECT_TRUE(llvm::is_contained(Features, "+fp8dot2"));
1434   EXPECT_TRUE(llvm::is_contained(Features, "+ssve-fp8dot2"));
1435   EXPECT_TRUE(llvm::is_contained(Features, "+fp8dot4"));
1436   EXPECT_TRUE(llvm::is_contained(Features, "+ssve-fp8dot4"));
1437   EXPECT_TRUE(llvm::is_contained(Features, "+f8f32mm"));
1438   EXPECT_TRUE(llvm::is_contained(Features, "+f8f16mm"));
1439   EXPECT_TRUE(llvm::is_contained(Features, "+lut"));
1440   EXPECT_TRUE(llvm::is_contained(Features, "+sme-lutv2"));
1441   EXPECT_TRUE(llvm::is_contained(Features, "+sme-f8f16"));
1442   EXPECT_TRUE(llvm::is_contained(Features, "+sme-f8f32"));
1443   EXPECT_TRUE(llvm::is_contained(Features, "+sme-fa64"));
1444   EXPECT_TRUE(llvm::is_contained(Features, "+cpa"));
1445   EXPECT_TRUE(llvm::is_contained(Features, "+pauth-lr"));
1446   EXPECT_TRUE(llvm::is_contained(Features, "+tlbiw"));
1447   EXPECT_TRUE(llvm::is_contained(Features, "+jsconv"));
1448   EXPECT_TRUE(llvm::is_contained(Features, "+complxnum"));
1449   EXPECT_TRUE(llvm::is_contained(Features, "+lsfe"));
1450   EXPECT_TRUE(llvm::is_contained(Features, "+fprcvt"));
1451   EXPECT_TRUE(llvm::is_contained(Features, "+cmpbr"));
1452   EXPECT_TRUE(llvm::is_contained(Features, "+lsui"));
1453   EXPECT_TRUE(llvm::is_contained(Features, "+occmo"));
1454   EXPECT_TRUE(llvm::is_contained(Features, "+pcdphint"));
1455   EXPECT_TRUE(llvm::is_contained(Features, "+pops"));
1456   EXPECT_TRUE(llvm::is_contained(Features, "+sme-mop4"));
1457   EXPECT_TRUE(llvm::is_contained(Features, "+sme-tmop"));
1458 
1459   // Assuming we listed every extension above, this should produce the same
1460   // result.
1461   std::vector<StringRef> AllFeatures;
1462   EXPECT_TRUE(AArch64::getExtensionFeatures(ExtVal, AllFeatures));
1463   EXPECT_THAT(Features, ::testing::ContainerEq(AllFeatures));
1464 }
1465 
1466 TEST(TargetParserTest, AArch64ArchFeatures) {
1467   EXPECT_EQ(AArch64::ARMV8A.ArchFeature, "+v8a");
1468   EXPECT_EQ(AArch64::ARMV8_1A.ArchFeature, "+v8.1a");
1469   EXPECT_EQ(AArch64::ARMV8_2A.ArchFeature, "+v8.2a");
1470   EXPECT_EQ(AArch64::ARMV8_3A.ArchFeature, "+v8.3a");
1471   EXPECT_EQ(AArch64::ARMV8_4A.ArchFeature, "+v8.4a");
1472   EXPECT_EQ(AArch64::ARMV8_5A.ArchFeature, "+v8.5a");
1473   EXPECT_EQ(AArch64::ARMV8_6A.ArchFeature, "+v8.6a");
1474   EXPECT_EQ(AArch64::ARMV8_7A.ArchFeature, "+v8.7a");
1475   EXPECT_EQ(AArch64::ARMV8_8A.ArchFeature, "+v8.8a");
1476   EXPECT_EQ(AArch64::ARMV8_9A.ArchFeature, "+v8.9a");
1477   EXPECT_EQ(AArch64::ARMV9A.ArchFeature, "+v9a");
1478   EXPECT_EQ(AArch64::ARMV9_1A.ArchFeature, "+v9.1a");
1479   EXPECT_EQ(AArch64::ARMV9_2A.ArchFeature, "+v9.2a");
1480   EXPECT_EQ(AArch64::ARMV9_3A.ArchFeature, "+v9.3a");
1481   EXPECT_EQ(AArch64::ARMV9_4A.ArchFeature, "+v9.4a");
1482   EXPECT_EQ(AArch64::ARMV9_5A.ArchFeature, "+v9.5a");
1483   EXPECT_EQ(AArch64::ARMV9_6A.ArchFeature, "+v9.6a");
1484   EXPECT_EQ(AArch64::ARMV8R.ArchFeature, "+v8r");
1485 }
1486 
1487 TEST(TargetParserTest, AArch64ArchPartialOrder) {
1488   for (const auto *A : AArch64::ArchInfos) {
1489     EXPECT_EQ(*A, *A);
1490 
1491     // v8r has no relation to other valid architectures
1492     if (*A != AArch64::ARMV8R) {
1493       EXPECT_FALSE(A->implies(AArch64::ARMV8R));
1494       EXPECT_FALSE(AArch64::ARMV8R.implies(*A));
1495     }
1496   }
1497 
1498   for (const auto *A : {
1499            &AArch64::ARMV8_1A,
1500            &AArch64::ARMV8_2A,
1501            &AArch64::ARMV8_3A,
1502            &AArch64::ARMV8_4A,
1503            &AArch64::ARMV8_5A,
1504            &AArch64::ARMV8_6A,
1505            &AArch64::ARMV8_7A,
1506            &AArch64::ARMV8_8A,
1507            &AArch64::ARMV8_9A,
1508        })
1509     EXPECT_TRUE(A->implies(AArch64::ARMV8A));
1510 
1511   for (const auto *A :
1512        {&AArch64::ARMV9_1A, &AArch64::ARMV9_2A, &AArch64::ARMV9_3A,
1513         &AArch64::ARMV9_4A, &AArch64::ARMV9_5A, &AArch64::ARMV9_6A})
1514     EXPECT_TRUE(A->implies(AArch64::ARMV9A));
1515 
1516   EXPECT_TRUE(AArch64::ARMV8_1A.implies(AArch64::ARMV8A));
1517   EXPECT_TRUE(AArch64::ARMV8_2A.implies(AArch64::ARMV8_1A));
1518   EXPECT_TRUE(AArch64::ARMV8_3A.implies(AArch64::ARMV8_2A));
1519   EXPECT_TRUE(AArch64::ARMV8_4A.implies(AArch64::ARMV8_3A));
1520   EXPECT_TRUE(AArch64::ARMV8_5A.implies(AArch64::ARMV8_4A));
1521   EXPECT_TRUE(AArch64::ARMV8_6A.implies(AArch64::ARMV8_5A));
1522   EXPECT_TRUE(AArch64::ARMV8_7A.implies(AArch64::ARMV8_6A));
1523   EXPECT_TRUE(AArch64::ARMV8_8A.implies(AArch64::ARMV8_7A));
1524   EXPECT_TRUE(AArch64::ARMV8_9A.implies(AArch64::ARMV8_8A));
1525 
1526   EXPECT_TRUE(AArch64::ARMV9_1A.implies(AArch64::ARMV9A));
1527   EXPECT_TRUE(AArch64::ARMV9_2A.implies(AArch64::ARMV9_1A));
1528   EXPECT_TRUE(AArch64::ARMV9_3A.implies(AArch64::ARMV9_2A));
1529   EXPECT_TRUE(AArch64::ARMV9_4A.implies(AArch64::ARMV9_3A));
1530   EXPECT_TRUE(AArch64::ARMV9_5A.implies(AArch64::ARMV9_4A));
1531   EXPECT_TRUE(AArch64::ARMV9_6A.implies(AArch64::ARMV9_5A));
1532 
1533   EXPECT_TRUE(AArch64::ARMV9A.implies(AArch64::ARMV8_5A));
1534   EXPECT_TRUE(AArch64::ARMV9_1A.implies(AArch64::ARMV8_6A));
1535   EXPECT_TRUE(AArch64::ARMV9_2A.implies(AArch64::ARMV8_7A));
1536   EXPECT_TRUE(AArch64::ARMV9_3A.implies(AArch64::ARMV8_8A));
1537   EXPECT_TRUE(AArch64::ARMV9_4A.implies(AArch64::ARMV8_9A));
1538 }
1539 
1540 TEST(TargetParserTest, AArch64ArchExtFeature) {
1541   const char *ArchExt[][4] = {
1542       {"crc", "nocrc", "+crc", "-crc"},
1543       {"crypto", "nocrypto", "+crypto", "-crypto"},
1544       {"flagm", "noflagm", "+flagm", "-flagm"},
1545       {"fp", "nofp", "+fp-armv8", "-fp-armv8"},
1546       {"simd", "nosimd", "+neon", "-neon"},
1547       {"fp16", "nofp16", "+fullfp16", "-fullfp16"},
1548       {"fp16fml", "nofp16fml", "+fp16fml", "-fp16fml"},
1549       {"profile", "noprofile", "+spe", "-spe"},
1550       {"ras", "noras", "+ras", "-ras"},
1551       {"lse", "nolse", "+lse", "-lse"},
1552       {"rdm", "nordm", "+rdm", "-rdm"},
1553       {"sve", "nosve", "+sve", "-sve"},
1554       {"sve-b16b16", "nosve-b16b16", "+sve-b16b16", "-sve-b16b16"},
1555       {"sve-bfscale", "nosve-bfscale", "+sve-bfscale", "-sve-bfscale"},
1556       {"sve-f16f32mm", "nosve-f16f32mm", "+sve-f16f32mm", "-sve-f16f32mm"},
1557       {"sve2", "nosve2", "+sve2", "-sve2"},
1558       {"sve-aes", "nosve-aes", "+sve-aes", "-sve-aes"},
1559       {"sve2-aes", "nosve2-aes", "+sve2-aes", "-sve2-aes"},
1560       {"sve2-sm4", "nosve2-sm4", "+sve2-sm4", "-sve2-sm4"},
1561       {"sve2-sha3", "nosve2-sha3", "+sve2-sha3", "-sve2-sha3"},
1562       {"sve2p1", "nosve2p1", "+sve2p1", "-sve2p1"},
1563       {"sve2p2", "nosve2p2", "+sve2p2", "-sve2p2"},
1564       {"sve-bitperm", "nosve-bitperm", "+sve-bitperm", "-sve-bitperm"},
1565       {"ssve-bitperm", "nossve-bitperm", "+ssve-bitperm", "-ssve-bitperm"},
1566       {"sve2-bitperm", "nosve2-bitperm", "+sve2-bitperm", "-sve2-bitperm"},
1567       {"sve-aes2", "nosve-aes2", "+sve-aes2", "-sve-aes2"},
1568       {"ssve-aes", "nossve-aes", "+ssve-aes", "-ssve-aes"},
1569       {"dotprod", "nodotprod", "+dotprod", "-dotprod"},
1570       {"rcpc", "norcpc", "+rcpc", "-rcpc"},
1571       {"rng", "norng", "+rand", "-rand"},
1572       {"memtag", "nomemtag", "+mte", "-mte"},
1573       {"tme", "notme", "+tme", "-tme"},
1574       {"pauth", "nopauth", "+pauth", "-pauth"},
1575       {"ssbs", "nossbs", "+ssbs", "-ssbs"},
1576       {"sb", "nosb", "+sb", "-sb"},
1577       {"predres", "nopredres", "+predres", "-predres"},
1578       {"i8mm", "noi8mm", "+i8mm", "-i8mm"},
1579       {"f32mm", "nof32mm", "+f32mm", "-f32mm"},
1580       {"f64mm", "nof64mm", "+f64mm", "-f64mm"},
1581       {"f8f32mm", "nof8f32mm", "+f8f32mm", "-f8f32mm"},
1582       {"f8f16mm", "nof8f16mm", "+f8f16mm", "-f8f16mm"},
1583       {"sme", "nosme", "+sme", "-sme"},
1584       {"sme-fa64", "nosme-fa64", "+sme-fa64", "-sme-fa64"},
1585       {"sme-f64f64", "nosme-f64f64", "+sme-f64f64", "-sme-f64f64"},
1586       {"sme-i16i64", "nosme-i16i64", "+sme-i16i64", "-sme-i16i64"},
1587       {"sme-f16f16", "nosme-f16f16", "+sme-f16f16", "-sme-f16f16"},
1588       {"sme2", "nosme2", "+sme2", "-sme2"},
1589       {"sme-b16b16", "nosme-b16b16", "+sme-b16b16", "-sme-b16b16"},
1590       {"sme2p1", "nosme2p1", "+sme2p1", "-sme2p1"},
1591       {"sme2p2", "nosme2p2", "+sme2p2", "-sme2p2"},
1592       {"hbc", "nohbc", "+hbc", "-hbc"},
1593       {"mops", "nomops", "+mops", "-mops"},
1594       {"pmuv3", "nopmuv3", "+perfmon", "-perfmon"},
1595       {"predres2", "nopredres2", "+specres2", "-specres2"},
1596       {"rasv2", "norasv2", "+rasv2", "-rasv2"},
1597       {"gcs", "nogcs", "+gcs", "-gcs"},
1598       {"fp8", "nofp8", "+fp8", "-fp8"},
1599       {"faminmax", "nofaminmax", "+faminmax", "-faminmax"},
1600       {"fp8fma", "nofp8fma", "+fp8fma", "-fp8fma"},
1601       {"ssve-fp8fma", "nossve-fp8fma", "+ssve-fp8fma", "-ssve-fp8fma"},
1602       {"fp8dot2", "nofp8dot2", "+fp8dot2", "-fp8dot2"},
1603       {"ssve-fp8dot2", "nossve-fp8dot2", "+ssve-fp8dot2", "-ssve-fp8dot2"},
1604       {"fp8dot4", "nofp8dot4", "+fp8dot4", "-fp8dot4"},
1605       {"ssve-fp8dot4", "nossve-fp8dot4", "+ssve-fp8dot4", "-ssve-fp8dot4"},
1606       {"lut", "nolut", "+lut", "-lut"},
1607       {"sme-lutv2", "nosme-lutv2", "+sme-lutv2", "-sme-lutv2"},
1608       {"sme-f8f16", "nosme-f8f16", "+sme-f8f16", "-sme-f8f16"},
1609       {"sme-f8f32", "nosme-f8f32", "+sme-f8f32", "-sme-f8f32"},
1610       {"lsfe", "nolsfe", "+lsfe", "-lsfe"},
1611       {"fprcvt", "nofprcvt", "+fprcvt", "-fprcvt"},
1612       {"cmpbr", "nocmpbr", "+cmpbr", "-cmpbr"},
1613       {"lsui", "nolsui", "+lsui", "-lsui"},
1614       {"occmo", "nooccmo", "+occmo", "-occmo"},
1615       {"pcdphint", "nopcdphint", "+pcdphint", "-pcdphint"},
1616       {"pops", "nopops", "+pops", "-pops"},
1617       {"sme-mop4", "nosme-mop4", "+sme-mop4", "-sme-mop4"},
1618       {"sme-tmop", "nosme-tmop", "+sme-tmop", "-sme-tmop"},
1619   };
1620 
1621   for (unsigned i = 0; i < std::size(ArchExt); i++) {
1622     EXPECT_EQ(StringRef(ArchExt[i][2]),
1623               AArch64::getArchExtFeature(ArchExt[i][0]));
1624     EXPECT_EQ(StringRef(ArchExt[i][3]),
1625               AArch64::getArchExtFeature(ArchExt[i][1]));
1626   }
1627 }
1628 
1629 TEST(TargetParserTest, AArch64PrintSupportedExtensions) {
1630   std::string expected = "All available -march extensions for AArch64\n\n"
1631                          "    Name                Architecture Feature(s)      "
1632                          "                          Description\n";
1633 
1634   outs().flush();
1635   testing::internal::CaptureStdout();
1636   AArch64::PrintSupportedExtensions();
1637   outs().flush();
1638   std::string captured = testing::internal::GetCapturedStdout();
1639 
1640   // Check that the start of the output is as expected.
1641   EXPECT_EQ(0ULL, captured.find(expected));
1642 
1643   // Should not include "none".
1644   EXPECT_EQ(std::string::npos, captured.find("none"));
1645   // Should not include anything that lacks a feature name. Checking a few here
1646   // but not all as if one is hidden correctly the rest should be.
1647   EXPECT_EQ(std::string::npos, captured.find("memtag3"));
1648   EXPECT_EQ(std::string::npos, captured.find("sha1"));
1649   EXPECT_EQ(std::string::npos, captured.find("ssbs2"));
1650 }
1651 
1652 struct AArch64ExtensionDependenciesBaseArchTestParams {
1653   const llvm::AArch64::ArchInfo &Arch;
1654   std::vector<StringRef> Modifiers;
1655   std::vector<StringRef> ExpectedPos;
1656   std::vector<StringRef> ExpectedNeg;
1657 };
1658 
1659 class AArch64ExtensionDependenciesBaseArchTestFixture
1660     : public ::testing::TestWithParam<
1661           AArch64ExtensionDependenciesBaseArchTestParams> {};
1662 
1663 struct AArch64ExtensionDependenciesBaseCPUTestParams {
1664   StringRef CPUName;
1665   std::vector<StringRef> Modifiers;
1666   std::vector<StringRef> ExpectedPos;
1667   std::vector<StringRef> ExpectedNeg;
1668 };
1669 
1670 class AArch64ExtensionDependenciesBaseCPUTestFixture
1671     : public ::testing::TestWithParam<
1672           AArch64ExtensionDependenciesBaseCPUTestParams> {};
1673 
1674 TEST_P(AArch64ExtensionDependenciesBaseArchTestFixture,
1675        AArch64ExtensionDependenciesBaseArch) {
1676   auto Params = GetParam();
1677 
1678   llvm::AArch64::ExtensionSet Extensions;
1679   Extensions.addArchDefaults(Params.Arch);
1680   for (auto M : Params.Modifiers) {
1681     bool success = Extensions.parseModifier(M);
1682     EXPECT_TRUE(success);
1683   }
1684   std::vector<StringRef> Features;
1685   Extensions.toLLVMFeatureList(Features);
1686 
1687   for (auto E : Params.ExpectedPos) {
1688     std::string PosString = "+";
1689     PosString += E;
1690     std::string NegString = "-";
1691     NegString += E;
1692     ASSERT_THAT(Features, Contains(StrEq(PosString)));
1693     ASSERT_THAT(Features, Not(Contains(StrEq(NegString))));
1694   }
1695 
1696   for (auto E : Params.ExpectedNeg) {
1697     std::string PosString = "+";
1698     PosString += E;
1699     ASSERT_THAT(Features, Not(Contains(StrEq(PosString))));
1700     // Features default to off, so the negative string is not expected in many
1701     // cases.
1702   }
1703 }
1704 
1705 TEST_P(AArch64ExtensionDependenciesBaseCPUTestFixture,
1706        AArch64ExtensionDependenciesBaseCPU) {
1707   auto Params = GetParam();
1708 
1709   llvm::AArch64::ExtensionSet Extensions;
1710   const std::optional<llvm::AArch64::CpuInfo> CPU =
1711       llvm::AArch64::parseCpu(Params.CPUName);
1712   EXPECT_TRUE(CPU);
1713   Extensions.addCPUDefaults(*CPU);
1714   for (auto M : Params.Modifiers) {
1715     bool success = Extensions.parseModifier(M);
1716     EXPECT_TRUE(success);
1717   }
1718   std::vector<StringRef> Features;
1719   Extensions.toLLVMFeatureList(Features);
1720 
1721   for (auto E : Params.ExpectedPos) {
1722     std::string PosString = "+";
1723     PosString += E;
1724     std::string NegString = "-";
1725     NegString += E;
1726     ASSERT_THAT(Features, Contains(StrEq(PosString)));
1727     ASSERT_THAT(Features, Not(Contains(StrEq(NegString))));
1728   }
1729 
1730   for (auto E : Params.ExpectedNeg) {
1731     std::string PosString = "+";
1732     PosString += E;
1733     ASSERT_THAT(Features, Not(Contains(StrEq(PosString))));
1734     // Features default to off, so the negative string is not expected in many
1735     // cases.
1736   }
1737 }
1738 
1739 AArch64ExtensionDependenciesBaseArchTestParams
1740     AArch64ExtensionDependenciesArchData[] = {
1741         // Base architecture features
1742         {AArch64::ARMV8A, {}, {"v8a", "fp-armv8", "neon"}, {}},
1743         {AArch64::ARMV8_1A,
1744          {},
1745          {"v8.1a", "crc", "fp-armv8", "lse", "rdm", "neon"},
1746          {}},
1747         {AArch64::ARMV9_5A, {}, {"v9.5a", "mops", "cpa"}, {}},
1748 
1749         // Positive modifiers
1750         {AArch64::ARMV8A, {"fp16"}, {"fullfp16"}, {}},
1751         {AArch64::ARMV8A, {"dotprod"}, {"dotprod"}, {}},
1752 
1753         // Negative modifiers
1754         {AArch64::ARMV8A, {"nofp"}, {"v8a"}, {"fp-armv8", "neon"}},
1755 
1756         // Mixed modifiers
1757         {AArch64::ARMV8A,
1758          {"fp16", "nofp16"},
1759          {"v8a", "fp-armv8", "neon"},
1760          {"fullfp16"}},
1761         {AArch64::ARMV8A,
1762          {"fp16", "nofp"},
1763          {"v8a"},
1764          {"fp-armv8", "neon", "fullfp16"}},
1765 
1766         // Long dependency chains: sve2-bitperm -> sve2 -> sve -> fp16 -> fp
1767         {AArch64::ARMV8A,
1768          {"nofp", "sve2", "sve-bitperm"},
1769          {"fp-armv8", "fullfp16", "sve", "sve2", "sve-bitperm"},
1770          {}},
1771         {AArch64::ARMV8A,
1772          {"sve2", "sve-bitperm", "nofp16"},
1773          {"fp-armv8"},
1774          {"full-fp16", "sve", "sve2", "sve-bitperm"}},
1775 
1776         // Meaning of +crypto varies with base architecture.
1777         {AArch64::ARMV8A, {"crypto"}, {"aes", "sha2"}, {}},
1778         {AArch64::ARMV8_4A, {"crypto"}, {"aes", "sha2", "sha3", "sm4"}, {}},
1779         {AArch64::ARMV9A, {"crypto"}, {"aes", "sha2", "sha3", "sm4"}, {}},
1780 
1781         // -crypto always disables all crypto features, even if it wouldn't
1782         // enable them.
1783         {AArch64::ARMV8A,
1784          {"aes", "sha2", "sha3", "sm4", "nocrypto"},
1785          {},
1786          {"aes", "sha2", "sha3", "sm4"}},
1787         {AArch64::ARMV8_4A,
1788          {"aes", "sha2", "sha3", "sm4", "nocrypto"},
1789          {},
1790          {"aes", "sha2", "sha3", "sm4"}},
1791 
1792         // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+
1793         {AArch64::ARMV8_3A, {"fp16"}, {"fullfp16"}, {"fp16fml"}},
1794         {AArch64::ARMV9A, {"fp16"}, {"fullfp16"}, {"fp16fml"}},
1795         {AArch64::ARMV8_4A, {"fp16"}, {"fullfp16", "fp16fml"}, {}},
1796 
1797         // fp -> fp16
1798         {AArch64::ARMV8A, {"nofp", "fp16"}, {"fp-armv8", "fullfp16"}, {}},
1799         {AArch64::ARMV8A, {"fp16", "nofp"}, {}, {"fp-armv8", "fullfp16"}},
1800 
1801         // fp -> simd
1802         {AArch64::ARMV8A, {"nofp", "simd"}, {"fp-armv8", "neon"}, {}},
1803         {AArch64::ARMV8A, {"simd", "nofp"}, {}, {"fp-armv8", "neon"}},
1804 
1805         // fp -> jscvt
1806         {AArch64::ARMV8A, {"nofp", "jscvt"}, {"fp-armv8", "jsconv"}, {}},
1807         {AArch64::ARMV8A, {"jscvt", "nofp"}, {}, {"fp-armv8", "jsconv"}},
1808 
1809         // fp -> lsfe
1810         {AArch64::ARMV9_6A, {"nofp", "lsfe"}, {"fp-armv8", "lsfe"}, {}},
1811         {AArch64::ARMV9_6A, {"lsfe", "nofp"}, {}, {"fp-armv8", "lsfe"}},
1812 
1813         // fp -> fprcvt
1814         {AArch64::ARMV9_6A, {"nofp", "fprcvt"}, {"fp-armv8", "fprcvt"}, {}},
1815         {AArch64::ARMV9_6A, {"fprcvt", "nofp"}, {}, {"fp-armv8", "fprcvt"}},
1816 
1817         // simd -> {aes, sha2, sha3, sm4, f8f16mm, f8f32mm, fp8dot4, fp8dot2}
1818         {AArch64::ARMV8A, {"nosimd", "aes"}, {"neon", "aes"}, {}},
1819         {AArch64::ARMV8A, {"aes", "nosimd"}, {}, {"neon", "aes"}},
1820         {AArch64::ARMV8A, {"nosimd", "sha2"}, {"neon", "sha2"}, {}},
1821         {AArch64::ARMV8A, {"sha2", "nosimd"}, {}, {"neon", "sha2"}},
1822         {AArch64::ARMV8A, {"nosimd", "sha3"}, {"neon", "sha3"}, {}},
1823         {AArch64::ARMV8A, {"sha3", "nosimd"}, {}, {"neon", "sha3"}},
1824         {AArch64::ARMV8A, {"nosimd", "sm4"}, {"neon", "sm4"}, {}},
1825         {AArch64::ARMV8A, {"sm4", "nosimd"}, {}, {"neon", "sm4"}},
1826         {AArch64::ARMV9_6A, {"nosimd", "f8f16mm"}, {"neon", "f8f16mm"}, {}},
1827         {AArch64::ARMV9_6A, {"f8f16mm", "nosimd"}, {}, {"neon", "f8f16mm"}},
1828         {AArch64::ARMV9_6A, {"nosimd", "f8f32mm"}, {"neon", "f8f32mm"}, {}},
1829         {AArch64::ARMV9_6A, {"f8f32mm", "nosimd"}, {}, {"neon", "f8f32mm"}},
1830         {AArch64::ARMV9_6A, {"nosimd", "fp8dot4"}, {"neon", "fp8dot4"}, {}},
1831         {AArch64::ARMV9_6A, {"fp8dot4", "nosimd"}, {}, {"neon", "fp8dot4"}},
1832         {AArch64::ARMV9_6A, {"nosimd", "fp8dot2"}, {"neon", "fp8dot2"}, {}},
1833         {AArch64::ARMV9_6A, {"fp8dot2", "nosimd"}, {}, {"neon", "fp8dot2"}},
1834 
1835         // simd -> {rdm, dotprod, fcma}
1836         {AArch64::ARMV8A, {"nosimd", "rdm"}, {"neon", "rdm"}, {}},
1837         {AArch64::ARMV8A, {"rdm", "nosimd"}, {}, {"neon", "rdm"}},
1838         {AArch64::ARMV8A, {"nosimd", "dotprod"}, {"neon", "dotprod"}, {}},
1839         {AArch64::ARMV8A, {"dotprod", "nosimd"}, {}, {"neon", "dotprod"}},
1840         {AArch64::ARMV8A, {"nosimd", "fcma"}, {"neon", "complxnum"}, {}},
1841         {AArch64::ARMV8A, {"fcma", "nosimd"}, {}, {"neon", "complxnum"}},
1842 
1843         // fp16 -> {fp16fml, sve}
1844         {AArch64::ARMV8A, {"nofp16", "fp16fml"}, {"fullfp16", "fp16fml"}, {}},
1845         {AArch64::ARMV8A, {"fp16fml", "nofp16"}, {}, {"fullfp16", "fp16fml"}},
1846         {AArch64::ARMV8A, {"nofp16", "sve"}, {"fullfp16", "sve"}, {}},
1847         {AArch64::ARMV8A, {"sve", "nofp16"}, {}, {"fullfp16", "sve"}},
1848 
1849         // bf16 -> {sme}
1850         {AArch64::ARMV8A, {"nobf16", "sme"}, {"bf16", "sme"}, {}},
1851         {AArch64::ARMV8A, {"sme", "nobf16"}, {}, {"bf16", "sme"}},
1852 
1853         // sve -> {sve2, f32mm, f64mm, sve-f16f32mm}
1854         {AArch64::ARMV8A, {"nosve", "sve2"}, {"sve", "sve2"}, {}},
1855         {AArch64::ARMV8A, {"sve2", "nosve"}, {}, {"sve", "sve2"}},
1856         {AArch64::ARMV8A, {"nosve", "f32mm"}, {"sve", "f32mm"}, {}},
1857         {AArch64::ARMV8A, {"f32mm", "nosve"}, {}, {"sve", "f32mm"}},
1858         {AArch64::ARMV8A, {"nosve", "f64mm"}, {"sve", "f64mm"}, {}},
1859         {AArch64::ARMV8A, {"f64mm", "nosve"}, {}, {"sve", "f64mm"}},
1860         {AArch64::ARMV9_6A,
1861          {"nosve", "sve-f16f32mm"},
1862          {"sve", "sve-f16f32mm"},
1863          {}},
1864         {AArch64::ARMV9_6A,
1865          {"sve-f16f32mm", "nosve"},
1866          {},
1867          {"sve", "sve-f16f32mm"}},
1868 
1869         // aes -> {sve-aes}
1870         {AArch64::ARMV8A, {"noaes", "sve-aes"}, {"aes", "sve-aes"}, {}},
1871         {AArch64::ARMV8A, {"sve-aes", "noaes"}, {}, {"aes", "sve-aes"}},
1872 
1873         // sve2 -> {sve2p1, sve2-bitperm, sve2-sha3, sve2-sm4, sve2-aes}
1874         {AArch64::ARMV8A, {"nosve2", "sve2p1"}, {"sve2", "sve2p1"}, {}},
1875         {AArch64::ARMV8A, {"sve2p1", "nosve2"}, {}, {"sve2", "sve2p1"}},
1876         {AArch64::ARMV8A,
1877          {"nosve2", "sve2-bitperm"},
1878          {"sve2", "sve-bitperm"},
1879          {}},
1880         {AArch64::ARMV8A,
1881          {"sve2-bitperm", "nosve2"},
1882          {"sve"},
1883          {"sve-bitperm", "sve2", "sve2-bitperm"}},
1884         {AArch64::ARMV8A,
1885          {"ssve-bitperm", "nosve-bitperm"},
1886          {"sme"},
1887          {"ssve-bitperm", "sve-bitperm"}},
1888         {AArch64::ARMV8A,
1889          {"nosve-bitperm", "ssve-bitperm"},
1890          {"sve-bitperm", "sve-bitperm"},
1891          {""}},
1892         {AArch64::ARMV8A, {"nosve2", "sve2-sha3"}, {"sve2", "sve2-sha3"}, {}},
1893         {AArch64::ARMV8A, {"sve2-sha3", "nosve2"}, {}, {"sve2", "sve2-sha3"}},
1894         {AArch64::ARMV8A, {"nosve2", "sve2-sm4"}, {"sve2", "sve2-sm4"}, {}},
1895         {AArch64::ARMV8A, {"sve2-sm4", "nosve2"}, {}, {"sve2", "sve2-sm4"}},
1896         {AArch64::ARMV8A, {"nosve2", "sve2-aes"}, {"sve2", "sve2-aes"}, {}},
1897         {AArch64::ARMV8A, {"sve2-aes", "nosve2"}, {}, {"sve2", "sve2-aes"}},
1898 
1899         // sve-b16b16 -> {sme-b16b16}
1900         {AArch64::ARMV9_4A,
1901          {"nosve-b16b16", "sme-b16b16"},
1902          {"sve-b16b16", "sme-b16b16"},
1903          {}},
1904         {AArch64::ARMV9_4A,
1905          {"sme-b16b16", "nosve-b16b16"},
1906          {},
1907          {"sve-b16b16", "sme-b16b16"}},
1908 
1909         // sve2p1 -> {sve2p2}
1910         {AArch64::ARMV9_6A, {"nosve2p1", "sve2p2"}, {"sve2p1", "sve2p2"}, {}},
1911         {AArch64::ARMV9_6A, {"sve2p2", "nosve2p1"}, {}, {"sve2p1", "sve2p2"}},
1912 
1913         // sme -> {sme2, sme-f16f16, sme-f64f64, sme-i16i64, sme-fa64}
1914         {AArch64::ARMV8A, {"nosme", "sme2"}, {"sme", "sme2"}, {}},
1915         {AArch64::ARMV8A, {"sme2", "nosme"}, {}, {"sme", "sme2"}},
1916         {AArch64::ARMV8A, {"nosme", "sme-f16f16"}, {"sme", "sme-f16f16"}, {}},
1917         {AArch64::ARMV8A, {"sme-f16f16", "nosme"}, {}, {"sme", "sme-f16f16"}},
1918         {AArch64::ARMV8A, {"nosme", "sme-f64f64"}, {"sme", "sme-f64f64"}, {}},
1919         {AArch64::ARMV8A, {"sme-f64f64", "nosme"}, {}, {"sme", "sme-f64f64"}},
1920         {AArch64::ARMV8A, {"nosme", "sme-i16i64"}, {"sme", "sme-i16i64"}, {}},
1921         {AArch64::ARMV8A, {"sme-i16i64", "nosme"}, {}, {"sme", "sme-i16i64"}},
1922         {AArch64::ARMV8A, {"nosme", "sme-fa64"}, {"sme", "sme-fa64"}, {}},
1923         {AArch64::ARMV8A, {"sme-fa64", "nosme"}, {}, {"sme", "sme-fa64"}},
1924 
1925         // sme2 -> {sme2p1, ssve-fp8fma, ssve-fp8dot2, ssve-fp8dot4, sme-f8f16,
1926         // sme-f8f32, sme-b16b16, ssve-aes}
1927         {AArch64::ARMV8A, {"nosme2", "sme2p1"}, {"sme2", "sme2p1"}, {}},
1928         {AArch64::ARMV8A, {"sme2p1", "nosme2"}, {}, {"sme2", "sme2p1"}},
1929         {AArch64::ARMV8A,
1930          {"nosme2", "ssve-fp8fma"},
1931          {"sme2", "ssve-fp8fma"},
1932          {}},
1933         {AArch64::ARMV8A,
1934          {"ssve-fp8fma", "nosme2"},
1935          {},
1936          {"sme2", "ssve-fp8fma"}},
1937         {AArch64::ARMV8A,
1938          {"nosme2", "ssve-fp8dot2"},
1939          {"sme2", "ssve-fp8dot2"},
1940          {}},
1941         {AArch64::ARMV8A,
1942          {"ssve-fp8dot2", "nosme2"},
1943          {},
1944          {"sme2", "ssve-fp8dot2"}},
1945         {AArch64::ARMV8A,
1946          {"nosme2", "ssve-fp8dot4"},
1947          {"sme2", "ssve-fp8dot4"},
1948          {}},
1949         {AArch64::ARMV8A,
1950          {"ssve-fp8dot4", "nosme2"},
1951          {},
1952          {"sme2", "ssve-fp8dot4"}},
1953         {AArch64::ARMV8A, {"nosme2", "sme-f8f16"}, {"sme2", "sme-f8f16"}, {}},
1954         {AArch64::ARMV8A, {"sme-f8f16", "nosme2"}, {}, {"sme2", "sme-f8f16"}},
1955         {AArch64::ARMV8A, {"nosme2", "sme-f8f32"}, {"sme2", "sme-f8f32"}, {}},
1956         {AArch64::ARMV8A, {"sme-f8f32", "nosme2"}, {}, {"sme2", "sme-f8f32"}},
1957         {AArch64::ARMV8A, {"nosme2", "sme-b16b16"}, {"sme2", "sme-b16b16"}, {}},
1958         {AArch64::ARMV8A, {"sme-b16b16", "nosme2"}, {}, {"sme2", "sme-b16b16"}},
1959         {AArch64::ARMV9_6A, {"nosme2", "ssve-aes"}, {"sme2", "ssve-aes"}, {}},
1960         {AArch64::ARMV9_6A, {"ssve-aes", "nosme2"}, {}, {"ssve-aes", "sme2"}},
1961 
1962         // sme2p1 -> {sme2p2}
1963         {AArch64::ARMV9_6A, {"nosme2p1", "sme2p2"}, {"sme2p2", "sme2p1"}, {}},
1964         {AArch64::ARMV9_6A, {"sme2p2", "nosme2p1"}, {}, {"sme2p1", "sme2p2"}},
1965 
1966         // fp8 -> {sme-f8f16, sme-f8f32, f8f16mm, f8f32mm, fp8dot4, fp8dot2,
1967         // ssve-fp8dot4, ssve-fp8dot2}
1968         {AArch64::ARMV8A, {"nofp8", "sme-f8f16"}, {"fp8", "sme-f8f16"}, {}},
1969         {AArch64::ARMV8A, {"sme-f8f16", "nofp8"}, {}, {"fp8", "sme-f8f16"}},
1970         {AArch64::ARMV8A, {"nofp8", "sme-f8f32"}, {"fp8", "sme-f8f32"}, {}},
1971         {AArch64::ARMV8A, {"sme-f8f32", "nofp8"}, {}, {"fp8", "sme-f8f32"}},
1972         {AArch64::ARMV9_6A, {"nofp8", "f8f16mm"}, {"fp8", "f8f16mm"}, {}},
1973         {AArch64::ARMV9_6A, {"f8f16mm", "nofp8"}, {}, {"fp8", "f8f16mm"}},
1974         {AArch64::ARMV9_6A, {"nofp8", "f8f32mm"}, {"fp8", "f8f32mm"}, {}},
1975         {AArch64::ARMV9_6A, {"f8f32mm", "nofp8"}, {}, {"fp8", "f8f32mm"}},
1976         {AArch64::ARMV9_6A, {"nofp8", "fp8dot4"}, {"fp8", "fp8dot4"}, {}},
1977         {AArch64::ARMV9_6A, {"fp8dot4", "nofp8"}, {}, {"fp8", "fp8dot4"}},
1978         {AArch64::ARMV9_6A, {"nofp8", "fp8dot2"}, {"fp8", "fp8dot2"}, {}},
1979         {AArch64::ARMV9_6A, {"fp8dot2", "nofp8"}, {}, {"fp8", "fp8dot2"}},
1980         {AArch64::ARMV9_6A,
1981          {"nofp8", "ssve-fp8dot4"},
1982          {"fp8", "ssve-fp8dot4"},
1983          {}},
1984         {AArch64::ARMV9_6A,
1985          {"ssve-fp8dot4", "nofp8"},
1986          {},
1987          {"fp8", "ssve-fp8dot4"}},
1988         {AArch64::ARMV9_6A,
1989          {"nofp8", "ssve-fp8dot2"},
1990          {"fp8", "ssve-fp8dot2"},
1991          {}},
1992         {AArch64::ARMV9_6A,
1993          {"ssve-fp8dot2", "nofp8"},
1994          {},
1995          {"fp8", "ssve-fp8dot2"}},
1996 
1997         // lse -> lse128
1998         {AArch64::ARMV8A, {"nolse", "lse128"}, {"lse", "lse128"}, {}},
1999         {AArch64::ARMV8A, {"lse128", "nolse"}, {}, {"lse", "lse128"}},
2000 
2001         // predres -> predres2
2002         {AArch64::ARMV8A,
2003          {"nopredres", "predres2"},
2004          {"predres", "specres2"},
2005          {}},
2006         {AArch64::ARMV8A,
2007          {"predres2", "nopredres"},
2008          {},
2009          {"predres", "specres2"}},
2010 
2011         // ras -> ras2
2012         {AArch64::ARMV8A, {"noras", "rasv2"}, {"ras", "rasv2"}, {}},
2013         {AArch64::ARMV8A, {"rasv2", "noras"}, {}, {"ras", "rasv2"}},
2014 
2015         // rcpc -> rcpc3
2016         {AArch64::ARMV8A, {"norcpc", "rcpc3"}, {"rcpc", "rcpc3"}, {}},
2017         {AArch64::ARMV8A, {"rcpc3", "norcpc"}, {}, {"rcpc", "rcpc3"}},
2018 
2019         // sve-aes -> {ssve-aes, sve2-aes}
2020         {AArch64::ARMV9_6A,
2021          {"nosve-aes", "ssve-aes"},
2022          {"sve-aes", "ssve-aes"},
2023          {}},
2024         {AArch64::ARMV9_6A,
2025          {"ssve-aes", "nosve-aes"},
2026          {},
2027          {"ssve-aes", "sve-aes"}},
2028         {AArch64::ARMV9_6A,
2029          {"nosve-aes", "sve2-aes"},
2030          {"sve2-aes", "sve-aes"},
2031          {}},
2032         {AArch64::ARMV9_6A,
2033          {"sve2-aes", "nosve-aes"},
2034          {},
2035          {"sve2-aes", "sve-aes"}},
2036 
2037         // -sve2-aes should disable sve-aes (only)
2038         {AArch64::ARMV9_6A,
2039          {"sve2", "sve-aes", "nosve2-aes"},
2040          {"sve2"},
2041          {"sve2-aes", "sve-aes"}},
2042 
2043         // sme-tmop -> sme
2044         {AArch64::ARMV8A, {"nosme2", "sme-tmop"}, {"sme2", "sme-tmop"}, {}},
2045         {AArch64::ARMV8A, {"sme-tmop", "nosme2"}, {}, {"sme2", "sme-tmop"}},
2046 
2047         // sme-mop4 -> sme
2048         {AArch64::ARMV8A, {"nosme", "sme-mop4"}, {"sme", "sme-mop4"}, {}},
2049         {AArch64::ARMV8A, {"sme-mop4", "nosme"}, {}, {"sme", "sme-mop4"}}};
2050 
2051 INSTANTIATE_TEST_SUITE_P(
2052     AArch64ExtensionDependenciesBaseArch,
2053     AArch64ExtensionDependenciesBaseArchTestFixture,
2054     ::testing::ValuesIn(AArch64ExtensionDependenciesArchData));
2055 
2056 AArch64ExtensionDependenciesBaseCPUTestParams
2057     AArch64ExtensionDependenciesCPUData[] = {
2058         // Base CPU features
2059         {"cortex-a57",
2060          {},
2061          {"v8a", "aes", "crc", "fp-armv8", "sha2", "neon"},
2062          {}},
2063         {"cortex-r82",
2064          {},
2065          {"v8r", "crc", "dotprod", "fp-armv8", "fullfp16", "fp16fml", "lse",
2066           "ras", "rcpc", "rdm", "sb", "neon", "ssbs"},
2067          {}},
2068         {"cortex-a520",
2069          {},
2070          {"v9.2a",    "bf16",    "crc",  "dotprod",     "flagm", "fp-armv8",
2071           "fullfp16", "fp16fml", "i8mm", "lse",         "mte",   "pauth",
2072           "perfmon",  "predres", "ras",  "rcpc",        "rdm",   "sb",
2073           "neon",     "ssbs",    "sve",  "sve-bitperm", "sve2"},
2074          {}},
2075 
2076         // Negative modifiers
2077         {"cortex-r82",
2078          {"nofp"},
2079          {"v8r", "crc", "lse", "ras", "rcpc", "sb", "ssbs"},
2080          {"fp-armv8", "neon", "fullfp16", "fp16fml", "dotprod", "rdm"}},
2081 };
2082 
2083 INSTANTIATE_TEST_SUITE_P(
2084     AArch64ExtensionDependenciesBaseCPU,
2085     AArch64ExtensionDependenciesBaseCPUTestFixture,
2086     ::testing::ValuesIn(AArch64ExtensionDependenciesCPUData));
2087 
2088 } // namespace
2089