1 //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements a target parser to recognise hardware features such as
11 // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Support/ARMBuildAttributes.h"
16 #include "llvm/Support/TargetParser.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/ADT/Twine.h"
20 #include <cctype>
21 
22 using namespace llvm;
23 using namespace ARM;
24 using namespace AArch64;
25 using namespace AMDGPU;
26 
27 namespace {
28 
29 // List of canonical FPU names (use getFPUSynonym) and which architectural
30 // features they correspond to (use getFPUFeatures).
31 // FIXME: TableGen this.
32 // The entries must appear in the order listed in ARM::FPUKind for correct indexing
33 static const struct {
34   const char *NameCStr;
35   size_t NameLength;
36   ARM::FPUKind ID;
37   ARM::FPUVersion FPUVersion;
38   ARM::NeonSupportLevel NeonSupport;
39   ARM::FPURestriction Restriction;
40 
41   StringRef getName() const { return StringRef(NameCStr, NameLength); }
42 } FPUNames[] = {
43 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
44   { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
45 #include "llvm/Support/ARMTargetParser.def"
46 };
47 
48 // List of canonical arch names (use getArchSynonym).
49 // This table also provides the build attribute fields for CPU arch
50 // and Arch ID, according to the Addenda to the ARM ABI, chapters
51 // 2.4 and 2.3.5.2 respectively.
52 // FIXME: SubArch values were simplified to fit into the expectations
53 // of the triples and are not conforming with their official names.
54 // Check to see if the expectation should be changed.
55 // FIXME: TableGen this.
56 template <typename T> struct ArchNames {
57   const char *NameCStr;
58   size_t NameLength;
59   const char *CPUAttrCStr;
60   size_t CPUAttrLength;
61   const char *SubArchCStr;
62   size_t SubArchLength;
63   unsigned DefaultFPU;
64   unsigned ArchBaseExtensions;
65   T ID;
66   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
67 
68   StringRef getName() const { return StringRef(NameCStr, NameLength); }
69 
70   // CPU class in build attributes.
71   StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
72 
73   // Sub-Arch name.
74   StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
75 };
76 ArchNames<ARM::ArchKind> ARCHNames[] = {
77 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
78   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
79    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ARM::ArchKind::ID, ARCH_ATTR},
80 #include "llvm/Support/ARMTargetParser.def"
81 };
82 
83 ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
84  #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
85    {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
86     sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
87  #include "llvm/Support/AArch64TargetParser.def"
88  };
89 
90 
91 // List of Arch Extension names.
92 // FIXME: TableGen this.
93 static const struct {
94   const char *NameCStr;
95   size_t NameLength;
96   unsigned ID;
97   const char *Feature;
98   const char *NegFeature;
99 
100   StringRef getName() const { return StringRef(NameCStr, NameLength); }
101 } ARCHExtNames[] = {
102 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
103   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
104 #include "llvm/Support/ARMTargetParser.def"
105 },AArch64ARCHExtNames[] = {
106 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
107   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
108 #include "llvm/Support/AArch64TargetParser.def"
109 };
110 
111 // List of HWDiv names (use getHWDivSynonym) and which architectural
112 // features they correspond to (use getHWDivFeatures).
113 // FIXME: TableGen this.
114 static const struct {
115   const char *NameCStr;
116   size_t NameLength;
117   unsigned ID;
118 
119   StringRef getName() const { return StringRef(NameCStr, NameLength); }
120 } HWDivNames[] = {
121 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
122 #include "llvm/Support/ARMTargetParser.def"
123 };
124 
125 // List of CPU names and their arches.
126 // The same CPU can have multiple arches and can be default on multiple arches.
127 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
128 // When this becomes table-generated, we'd probably need two tables.
129 // FIXME: TableGen this.
130 template <typename T> struct CpuNames {
131   const char *NameCStr;
132   size_t NameLength;
133   T ArchID;
134   bool Default; // is $Name the default CPU for $ArchID ?
135   unsigned DefaultExtensions;
136 
137   StringRef getName() const { return StringRef(NameCStr, NameLength); }
138 };
139 CpuNames<ARM::ArchKind> CPUNames[] = {
140 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
141   { NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
142 #include "llvm/Support/ARMTargetParser.def"
143 };
144 
145 CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
146  #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
147    { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
148  #include "llvm/Support/AArch64TargetParser.def"
149  };
150 
151 } // namespace
152 
153 // ======================================================= //
154 // Information by ID
155 // ======================================================= //
156 
157 StringRef ARM::getFPUName(unsigned FPUKind) {
158   if (FPUKind >= ARM::FK_LAST)
159     return StringRef();
160   return FPUNames[FPUKind].getName();
161 }
162 
163 FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
164   if (FPUKind >= ARM::FK_LAST)
165     return FPUVersion::NONE;
166   return FPUNames[FPUKind].FPUVersion;
167 }
168 
169 ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
170   if (FPUKind >= ARM::FK_LAST)
171     return ARM::NeonSupportLevel::None;
172   return FPUNames[FPUKind].NeonSupport;
173 }
174 
175 ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
176   if (FPUKind >= ARM::FK_LAST)
177     return ARM::FPURestriction::None;
178   return FPUNames[FPUKind].Restriction;
179 }
180 
181 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, ArchKind AK) {
182   if (CPU == "generic")
183     return ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
184 
185   return StringSwitch<unsigned>(CPU)
186 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
187     .Case(NAME, DEFAULT_FPU)
188 #include "llvm/Support/ARMTargetParser.def"
189     .Default(ARM::FK_INVALID);
190 }
191 
192 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, ArchKind AK) {
193   if (CPU == "generic")
194     return ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
195 
196   return StringSwitch<unsigned>(CPU)
197 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
198     .Case(NAME, ARCHNames[static_cast<unsigned>(ARM::ArchKind::ID)]\
199             .ArchBaseExtensions | DEFAULT_EXT)
200 #include "llvm/Support/ARMTargetParser.def"
201     .Default(ARM::AEK_INVALID);
202 }
203 
204 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
205                                  std::vector<StringRef> &Features) {
206 
207   if (HWDivKind == ARM::AEK_INVALID)
208     return false;
209 
210   if (HWDivKind & ARM::AEK_HWDIVARM)
211     Features.push_back("+hwdiv-arm");
212   else
213     Features.push_back("-hwdiv-arm");
214 
215   if (HWDivKind & ARM::AEK_HWDIVTHUMB)
216     Features.push_back("+hwdiv");
217   else
218     Features.push_back("-hwdiv");
219 
220   return true;
221 }
222 
223 bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
224                                      std::vector<StringRef> &Features) {
225 
226   if (Extensions == ARM::AEK_INVALID)
227     return false;
228 
229   if (Extensions & ARM::AEK_CRC)
230     Features.push_back("+crc");
231   else
232     Features.push_back("-crc");
233 
234   if (Extensions & ARM::AEK_DSP)
235     Features.push_back("+dsp");
236   else
237     Features.push_back("-dsp");
238 
239   if (Extensions & ARM::AEK_FP16FML)
240     Features.push_back("+fp16fml");
241   else
242     Features.push_back("-fp16fml");
243 
244   if (Extensions & ARM::AEK_RAS)
245     Features.push_back("+ras");
246   else
247     Features.push_back("-ras");
248 
249   if (Extensions & ARM::AEK_DOTPROD)
250     Features.push_back("+dotprod");
251   else
252     Features.push_back("-dotprod");
253 
254   return getHWDivFeatures(Extensions, Features);
255 }
256 
257 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
258                                std::vector<StringRef> &Features) {
259 
260   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
261     return false;
262 
263   // fp-only-sp and d16 subtarget features are independent of each other, so we
264   // must enable/disable both.
265   switch (FPUNames[FPUKind].Restriction) {
266   case ARM::FPURestriction::SP_D16:
267     Features.push_back("+fp-only-sp");
268     Features.push_back("+d16");
269     break;
270   case ARM::FPURestriction::D16:
271     Features.push_back("-fp-only-sp");
272     Features.push_back("+d16");
273     break;
274   case ARM::FPURestriction::None:
275     Features.push_back("-fp-only-sp");
276     Features.push_back("-d16");
277     break;
278   }
279 
280   // FPU version subtarget features are inclusive of lower-numbered ones, so
281   // enable the one corresponding to this version and disable all that are
282   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
283   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
284   switch (FPUNames[FPUKind].FPUVersion) {
285   case ARM::FPUVersion::VFPV5:
286     Features.push_back("+fp-armv8");
287     break;
288   case ARM::FPUVersion::VFPV4:
289     Features.push_back("+vfp4");
290     Features.push_back("-fp-armv8");
291     break;
292   case ARM::FPUVersion::VFPV3_FP16:
293     Features.push_back("+vfp3");
294     Features.push_back("+fp16");
295     Features.push_back("-vfp4");
296     Features.push_back("-fp-armv8");
297     break;
298   case ARM::FPUVersion::VFPV3:
299     Features.push_back("+vfp3");
300     Features.push_back("-fp16");
301     Features.push_back("-vfp4");
302     Features.push_back("-fp-armv8");
303     break;
304   case ARM::FPUVersion::VFPV2:
305     Features.push_back("+vfp2");
306     Features.push_back("-vfp3");
307     Features.push_back("-fp16");
308     Features.push_back("-vfp4");
309     Features.push_back("-fp-armv8");
310     break;
311   case ARM::FPUVersion::NONE:
312     Features.push_back("-vfp2");
313     Features.push_back("-vfp3");
314     Features.push_back("-fp16");
315     Features.push_back("-vfp4");
316     Features.push_back("-fp-armv8");
317     break;
318   }
319 
320   // crypto includes neon, so we handle this similarly to FPU version.
321   switch (FPUNames[FPUKind].NeonSupport) {
322   case ARM::NeonSupportLevel::Crypto:
323     Features.push_back("+neon");
324     Features.push_back("+crypto");
325     break;
326   case ARM::NeonSupportLevel::Neon:
327     Features.push_back("+neon");
328     Features.push_back("-crypto");
329     break;
330   case ARM::NeonSupportLevel::None:
331     Features.push_back("-neon");
332     Features.push_back("-crypto");
333     break;
334   }
335 
336   return true;
337 }
338 
339 StringRef llvm::ARM::getArchName(ArchKind AK) {
340   return ARCHNames[static_cast<unsigned>(AK)].getName();
341 }
342 
343 StringRef llvm::ARM::getCPUAttr(ArchKind AK) {
344   return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
345 }
346 
347 StringRef llvm::ARM::getSubArch(ArchKind AK) {
348   return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
349 }
350 
351 unsigned llvm::ARM::getArchAttr(ArchKind AK) {
352   return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
353 }
354 
355 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
356   for (const auto AE : ARCHExtNames) {
357     if (ArchExtKind == AE.ID)
358       return AE.getName();
359   }
360   return StringRef();
361 }
362 
363 StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) {
364   if (ArchExt.startswith("no")) {
365     StringRef ArchExtBase(ArchExt.substr(2));
366     for (const auto AE : ARCHExtNames) {
367       if (AE.NegFeature && ArchExtBase == AE.getName())
368         return StringRef(AE.NegFeature);
369     }
370   }
371   for (const auto AE : ARCHExtNames) {
372     if (AE.Feature && ArchExt == AE.getName())
373       return StringRef(AE.Feature);
374   }
375 
376   return StringRef();
377 }
378 
379 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
380   for (const auto D : HWDivNames) {
381     if (HWDivKind == D.ID)
382       return D.getName();
383   }
384   return StringRef();
385 }
386 
387 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
388   ArchKind AK = parseArch(Arch);
389   if (AK == ARM::ArchKind::INVALID)
390     return StringRef();
391 
392   // Look for multiple AKs to find the default for pair AK+Name.
393   for (const auto CPU : CPUNames) {
394     if (CPU.ArchID == AK && CPU.Default)
395       return CPU.getName();
396   }
397 
398   // If we can't find a default then target the architecture instead
399   return "generic";
400 }
401 
402 StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
403   return ARM::getFPUName(FPUKind);
404 }
405 
406 ARM::FPUVersion AArch64::getFPUVersion(unsigned FPUKind) {
407   return ARM::getFPUVersion(FPUKind);
408 }
409 
410 ARM::NeonSupportLevel AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
411   return ARM::getFPUNeonSupportLevel( FPUKind);
412 }
413 
414 ARM::FPURestriction AArch64::getFPURestriction(unsigned FPUKind) {
415   return ARM::getFPURestriction(FPUKind);
416 }
417 
418 unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, ArchKind AK) {
419   if (CPU == "generic")
420     return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
421 
422   return StringSwitch<unsigned>(CPU)
423 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
424     .Case(NAME, DEFAULT_FPU)
425 #include "llvm/Support/AArch64TargetParser.def"
426     .Default(ARM::FK_INVALID);
427 }
428 
429 unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, ArchKind AK) {
430   if (CPU == "generic")
431     return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
432 
433   return StringSwitch<unsigned>(CPU)
434 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)       \
435   .Case(NAME,                                                                  \
436         AArch64ARCHNames[static_cast<unsigned>(AArch64::ArchKind::ID)] \
437             .ArchBaseExtensions | \
438             DEFAULT_EXT)
439 #include "llvm/Support/AArch64TargetParser.def"
440     .Default(AArch64::AEK_INVALID);
441 }
442 
443 AArch64::ArchKind llvm::AArch64::getCPUArchKind(StringRef CPU) {
444   if (CPU == "generic")
445     return AArch64::ArchKind::ARMV8A;
446 
447   return StringSwitch<AArch64::ArchKind>(CPU)
448 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
449   .Case(NAME, AArch64::ArchKind:: ID)
450 #include "llvm/Support/AArch64TargetParser.def"
451     .Default(AArch64::ArchKind::INVALID);
452 }
453 
454 bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
455                                      std::vector<StringRef> &Features) {
456 
457   if (Extensions == AArch64::AEK_INVALID)
458     return false;
459 
460   if (Extensions & AArch64::AEK_FP)
461     Features.push_back("+fp-armv8");
462   if (Extensions & AArch64::AEK_SIMD)
463     Features.push_back("+neon");
464   if (Extensions & AArch64::AEK_CRC)
465     Features.push_back("+crc");
466   if (Extensions & AArch64::AEK_CRYPTO)
467     Features.push_back("+crypto");
468   if (Extensions & AArch64::AEK_DOTPROD)
469     Features.push_back("+dotprod");
470   if (Extensions & AArch64::AEK_FP16FML)
471     Features.push_back("+fp16fml");
472   if (Extensions & AArch64::AEK_FP16)
473     Features.push_back("+fullfp16");
474   if (Extensions & AArch64::AEK_PROFILE)
475     Features.push_back("+spe");
476   if (Extensions & AArch64::AEK_RAS)
477     Features.push_back("+ras");
478   if (Extensions & AArch64::AEK_LSE)
479     Features.push_back("+lse");
480   if (Extensions & AArch64::AEK_RDM)
481     Features.push_back("+rdm");
482   if (Extensions & AArch64::AEK_SVE)
483     Features.push_back("+sve");
484   if (Extensions & AArch64::AEK_RCPC)
485     Features.push_back("+rcpc");
486 
487   return true;
488 }
489 
490 bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
491                                std::vector<StringRef> &Features) {
492   return ARM::getFPUFeatures(FPUKind, Features);
493 }
494 
495 bool llvm::AArch64::getArchFeatures(AArch64::ArchKind AK,
496                                     std::vector<StringRef> &Features) {
497   if (AK == AArch64::ArchKind::ARMV8_1A)
498     Features.push_back("+v8.1a");
499   if (AK == AArch64::ArchKind::ARMV8_2A)
500     Features.push_back("+v8.2a");
501   if (AK == AArch64::ArchKind::ARMV8_3A)
502     Features.push_back("+v8.3a");
503   if (AK == AArch64::ArchKind::ARMV8_4A)
504     Features.push_back("+v8.4a");
505 
506   return AK != AArch64::ArchKind::INVALID;
507 }
508 
509 StringRef llvm::AArch64::getArchName(ArchKind AK) {
510   return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
511 }
512 
513 StringRef llvm::AArch64::getCPUAttr(ArchKind AK) {
514   return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
515 }
516 
517 StringRef llvm::AArch64::getSubArch(ArchKind AK) {
518   return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
519 }
520 
521 unsigned llvm::AArch64::getArchAttr(ArchKind AK) {
522   return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
523 }
524 
525 StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
526   for (const auto &AE : AArch64ARCHExtNames)
527     if (ArchExtKind == AE.ID)
528       return AE.getName();
529   return StringRef();
530 }
531 
532 StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
533   if (ArchExt.startswith("no")) {
534     StringRef ArchExtBase(ArchExt.substr(2));
535     for (const auto &AE : AArch64ARCHExtNames) {
536       if (AE.NegFeature && ArchExtBase == AE.getName())
537         return StringRef(AE.NegFeature);
538     }
539   }
540 
541   for (const auto &AE : AArch64ARCHExtNames)
542     if (AE.Feature && ArchExt == AE.getName())
543       return StringRef(AE.Feature);
544   return StringRef();
545 }
546 
547 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
548   AArch64::ArchKind AK = parseArch(Arch);
549   if (AK == ArchKind::INVALID)
550     return StringRef();
551 
552   // Look for multiple AKs to find the default for pair AK+Name.
553   for (const auto &CPU : AArch64CPUNames)
554     if (CPU.ArchID == AK && CPU.Default)
555       return CPU.getName();
556 
557   // If we can't find a default then target the architecture instead
558   return "generic";
559 }
560 
561 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
562   if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
563     return (Arch[1] - 48);
564   return 0;
565 }
566 
567 // ======================================================= //
568 // Parsers
569 // ======================================================= //
570 
571 static StringRef getHWDivSynonym(StringRef HWDiv) {
572   return StringSwitch<StringRef>(HWDiv)
573       .Case("thumb,arm", "arm,thumb")
574       .Default(HWDiv);
575 }
576 
577 static StringRef getFPUSynonym(StringRef FPU) {
578   return StringSwitch<StringRef>(FPU)
579       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
580       .Case("vfp2", "vfpv2")
581       .Case("vfp3", "vfpv3")
582       .Case("vfp4", "vfpv4")
583       .Case("vfp3-d16", "vfpv3-d16")
584       .Case("vfp4-d16", "vfpv4-d16")
585       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
586       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
587       .Case("fp5-sp-d16", "fpv5-sp-d16")
588       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
589       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
590       .Case("neon-vfpv3", "neon")
591       .Default(FPU);
592 }
593 
594 static StringRef getArchSynonym(StringRef Arch) {
595   return StringSwitch<StringRef>(Arch)
596       .Case("v5", "v5t")
597       .Case("v5e", "v5te")
598       .Case("v6j", "v6")
599       .Case("v6hl", "v6k")
600       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
601       .Cases("v6z", "v6zk", "v6kz")
602       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
603       .Case("v7r", "v7-r")
604       .Case("v7m", "v7-m")
605       .Case("v7em", "v7e-m")
606       .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
607       .Case("v8.1a", "v8.1-a")
608       .Case("v8.2a", "v8.2-a")
609       .Case("v8.3a", "v8.3-a")
610       .Case("v8.4a", "v8.4-a")
611       .Case("v8r", "v8-r")
612       .Case("v8m.base", "v8-m.base")
613       .Case("v8m.main", "v8-m.main")
614       .Default(Arch);
615 }
616 
617 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
618 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
619 // "v.+", if the latter, return unmodified string, minus 'eb'.
620 // If invalid, return empty string.
621 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
622   size_t offset = StringRef::npos;
623   StringRef A = Arch;
624   StringRef Error = "";
625 
626   // Begins with "arm" / "thumb", move past it.
627   if (A.startswith("arm64"))
628     offset = 5;
629   else if (A.startswith("arm"))
630     offset = 3;
631   else if (A.startswith("thumb"))
632     offset = 5;
633   else if (A.startswith("aarch64")) {
634     offset = 7;
635     // AArch64 uses "_be", not "eb" suffix.
636     if (A.find("eb") != StringRef::npos)
637       return Error;
638     if (A.substr(offset, 3) == "_be")
639       offset += 3;
640   }
641 
642   // Ex. "armebv7", move past the "eb".
643   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
644     offset += 2;
645   // Or, if it ends with eb ("armv7eb"), chop it off.
646   else if (A.endswith("eb"))
647     A = A.substr(0, A.size() - 2);
648   // Trim the head
649   if (offset != StringRef::npos)
650     A = A.substr(offset);
651 
652   // Empty string means offset reached the end, which means it's valid.
653   if (A.empty())
654     return Arch;
655 
656   // Only match non-marketing names
657   if (offset != StringRef::npos) {
658     // Must start with 'vN'.
659     if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
660       return Error;
661     // Can't have an extra 'eb'.
662     if (A.find("eb") != StringRef::npos)
663       return Error;
664   }
665 
666   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
667   return A;
668 }
669 
670 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
671   StringRef Syn = getHWDivSynonym(HWDiv);
672   for (const auto D : HWDivNames) {
673     if (Syn == D.getName())
674       return D.ID;
675   }
676   return ARM::AEK_INVALID;
677 }
678 
679 unsigned llvm::ARM::parseFPU(StringRef FPU) {
680   StringRef Syn = getFPUSynonym(FPU);
681   for (const auto F : FPUNames) {
682     if (Syn == F.getName())
683       return F.ID;
684   }
685   return ARM::FK_INVALID;
686 }
687 
688 // Allows partial match, ex. "v7a" matches "armv7a".
689 ARM::ArchKind ARM::parseArch(StringRef Arch) {
690   Arch = getCanonicalArchName(Arch);
691   StringRef Syn = getArchSynonym(Arch);
692   for (const auto A : ARCHNames) {
693     if (A.getName().endswith(Syn))
694       return A.ID;
695   }
696   return ARM::ArchKind::INVALID;
697 }
698 
699 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
700   for (const auto A : ARCHExtNames) {
701     if (ArchExt == A.getName())
702       return A.ID;
703   }
704   return ARM::AEK_INVALID;
705 }
706 
707 ARM::ArchKind llvm::ARM::parseCPUArch(StringRef CPU) {
708   for (const auto C : CPUNames) {
709     if (CPU == C.getName())
710       return C.ArchID;
711   }
712   return ARM::ArchKind::INVALID;
713 }
714 
715 void llvm::ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
716   for (const CpuNames<ARM::ArchKind> &Arch : CPUNames) {
717     if (Arch.ArchID != ARM::ArchKind::INVALID)
718       Values.push_back(Arch.getName());
719   }
720 }
721 
722 void llvm::AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
723   for (const CpuNames<AArch64::ArchKind> &Arch : AArch64CPUNames) {
724     if (Arch.ArchID != AArch64::ArchKind::INVALID)
725       Values.push_back(Arch.getName());
726   }
727 }
728 
729 // ARM, Thumb, AArch64
730 ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
731   return StringSwitch<ARM::ISAKind>(Arch)
732       .StartsWith("aarch64", ARM::ISAKind::AARCH64)
733       .StartsWith("arm64", ARM::ISAKind::AARCH64)
734       .StartsWith("thumb", ARM::ISAKind::THUMB)
735       .StartsWith("arm", ARM::ISAKind::ARM)
736       .Default(ARM::ISAKind::INVALID);
737 }
738 
739 // Little/Big endian
740 ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
741   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
742       Arch.startswith("aarch64_be"))
743     return ARM::EndianKind::BIG;
744 
745   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
746     if (Arch.endswith("eb"))
747       return ARM::EndianKind::BIG;
748     else
749       return ARM::EndianKind::LITTLE;
750   }
751 
752   if (Arch.startswith("aarch64"))
753     return ARM::EndianKind::LITTLE;
754 
755   return ARM::EndianKind::INVALID;
756 }
757 
758 // Profile A/R/M
759 ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
760   Arch = getCanonicalArchName(Arch);
761   switch (parseArch(Arch)) {
762   case ARM::ArchKind::ARMV6M:
763   case ARM::ArchKind::ARMV7M:
764   case ARM::ArchKind::ARMV7EM:
765   case ARM::ArchKind::ARMV8MMainline:
766   case ARM::ArchKind::ARMV8MBaseline:
767     return ARM::ProfileKind::M;
768   case ARM::ArchKind::ARMV7R:
769   case ARM::ArchKind::ARMV8R:
770     return ARM::ProfileKind::R;
771   case ARM::ArchKind::ARMV7A:
772   case ARM::ArchKind::ARMV7VE:
773   case ARM::ArchKind::ARMV7K:
774   case ARM::ArchKind::ARMV8A:
775   case ARM::ArchKind::ARMV8_1A:
776   case ARM::ArchKind::ARMV8_2A:
777   case ARM::ArchKind::ARMV8_3A:
778   case ARM::ArchKind::ARMV8_4A:
779     return ARM::ProfileKind::A;
780   case ARM::ArchKind::ARMV2:
781   case ARM::ArchKind::ARMV2A:
782   case ARM::ArchKind::ARMV3:
783   case ARM::ArchKind::ARMV3M:
784   case ARM::ArchKind::ARMV4:
785   case ARM::ArchKind::ARMV4T:
786   case ARM::ArchKind::ARMV5T:
787   case ARM::ArchKind::ARMV5TE:
788   case ARM::ArchKind::ARMV5TEJ:
789   case ARM::ArchKind::ARMV6:
790   case ARM::ArchKind::ARMV6K:
791   case ARM::ArchKind::ARMV6T2:
792   case ARM::ArchKind::ARMV6KZ:
793   case ARM::ArchKind::ARMV7S:
794   case ARM::ArchKind::IWMMXT:
795   case ARM::ArchKind::IWMMXT2:
796   case ARM::ArchKind::XSCALE:
797   case ARM::ArchKind::INVALID:
798     return ARM::ProfileKind::INVALID;
799   }
800   llvm_unreachable("Unhandled architecture");
801 }
802 
803 // Version number (ex. v7 = 7).
804 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
805   Arch = getCanonicalArchName(Arch);
806   switch (parseArch(Arch)) {
807   case ARM::ArchKind::ARMV2:
808   case ARM::ArchKind::ARMV2A:
809     return 2;
810   case ARM::ArchKind::ARMV3:
811   case ARM::ArchKind::ARMV3M:
812     return 3;
813   case ARM::ArchKind::ARMV4:
814   case ARM::ArchKind::ARMV4T:
815     return 4;
816   case ARM::ArchKind::ARMV5T:
817   case ARM::ArchKind::ARMV5TE:
818   case ARM::ArchKind::IWMMXT:
819   case ARM::ArchKind::IWMMXT2:
820   case ARM::ArchKind::XSCALE:
821   case ARM::ArchKind::ARMV5TEJ:
822     return 5;
823   case ARM::ArchKind::ARMV6:
824   case ARM::ArchKind::ARMV6K:
825   case ARM::ArchKind::ARMV6T2:
826   case ARM::ArchKind::ARMV6KZ:
827   case ARM::ArchKind::ARMV6M:
828     return 6;
829   case ARM::ArchKind::ARMV7A:
830   case ARM::ArchKind::ARMV7VE:
831   case ARM::ArchKind::ARMV7R:
832   case ARM::ArchKind::ARMV7M:
833   case ARM::ArchKind::ARMV7S:
834   case ARM::ArchKind::ARMV7EM:
835   case ARM::ArchKind::ARMV7K:
836     return 7;
837   case ARM::ArchKind::ARMV8A:
838   case ARM::ArchKind::ARMV8_1A:
839   case ARM::ArchKind::ARMV8_2A:
840   case ARM::ArchKind::ARMV8_3A:
841   case ARM::ArchKind::ARMV8_4A:
842   case ARM::ArchKind::ARMV8R:
843   case ARM::ArchKind::ARMV8MBaseline:
844   case ARM::ArchKind::ARMV8MMainline:
845     return 8;
846   case ARM::ArchKind::INVALID:
847     return 0;
848   }
849   llvm_unreachable("Unhandled architecture");
850 }
851 
852 StringRef llvm::ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
853   StringRef ArchName =
854       CPU.empty() ? TT.getArchName() : ARM::getArchName(ARM::parseCPUArch(CPU));
855 
856   if (TT.isOSBinFormatMachO()) {
857     if (TT.getEnvironment() == Triple::EABI ||
858         TT.getOS() == Triple::UnknownOS ||
859         llvm::ARM::parseArchProfile(ArchName) == ARM::ProfileKind::M)
860       return "aapcs";
861     if (TT.isWatchABI())
862       return "aapcs16";
863     return "apcs-gnu";
864   } else if (TT.isOSWindows())
865     // FIXME: this is invalid for WindowsCE.
866     return "aapcs";
867 
868   // Select the default based on the platform.
869   switch (TT.getEnvironment()) {
870   case Triple::Android:
871   case Triple::GNUEABI:
872   case Triple::GNUEABIHF:
873   case Triple::MuslEABI:
874   case Triple::MuslEABIHF:
875     return "aapcs-linux";
876   case Triple::EABIHF:
877   case Triple::EABI:
878     return "aapcs";
879   default:
880     if (TT.isOSNetBSD())
881       return "apcs-gnu";
882     if (TT.isOSOpenBSD())
883       return "aapcs-linux";
884     return "aapcs";
885   }
886 }
887 
888 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
889   return ARM::getCanonicalArchName(Arch);
890 }
891 
892 unsigned llvm::AArch64::parseFPU(StringRef FPU) {
893   return ARM::parseFPU(FPU);
894 }
895 
896 // Allows partial match, ex. "v8a" matches "armv8a".
897 AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
898   Arch = getCanonicalArchName(Arch);
899   if (checkArchVersion(Arch) < 8)
900     return ArchKind::INVALID;
901 
902   StringRef Syn = getArchSynonym(Arch);
903   for (const auto A : AArch64ARCHNames) {
904     if (A.getName().endswith(Syn))
905       return A.ID;
906   }
907   return ArchKind::INVALID;
908 }
909 
910 AArch64::ArchExtKind llvm::AArch64::parseArchExt(StringRef ArchExt) {
911   for (const auto A : AArch64ARCHExtNames) {
912     if (ArchExt == A.getName())
913       return static_cast<ArchExtKind>(A.ID);
914   }
915   return AArch64::AEK_INVALID;
916 }
917 
918 AArch64::ArchKind llvm::AArch64::parseCPUArch(StringRef CPU) {
919   for (const auto C : AArch64CPUNames) {
920     if (CPU == C.getName())
921       return C.ArchID;
922   }
923   return ArchKind::INVALID;
924 }
925 
926 // ARM, Thumb, AArch64
927 ARM::ISAKind AArch64::parseArchISA(StringRef Arch) {
928   return ARM::parseArchISA(Arch);
929 }
930 
931 // Little/Big endian
932 ARM::EndianKind AArch64::parseArchEndian(StringRef Arch) {
933   return ARM::parseArchEndian(Arch);
934 }
935 
936 // Profile A/R/M
937 ARM::ProfileKind AArch64::parseArchProfile(StringRef Arch) {
938   return ARM::parseArchProfile(Arch);
939 }
940 
941 // Version number (ex. v8 = 8).
942 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
943   return ARM::parseArchVersion(Arch);
944 }
945 
946 bool llvm::AArch64::isX18ReservedByDefault(const Triple &TT) {
947   return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
948          TT.isOSWindows();
949 }
950 
951 namespace {
952 
953 struct GPUInfo {
954   StringLiteral Name;
955   StringLiteral CanonicalName;
956   AMDGPU::GPUKind Kind;
957   unsigned Features;
958 };
959 
960 constexpr GPUInfo R600GPUs[26] = {
961   // Name       Canonical    Kind        Features
962   //            Name
963   {{"r600"},    {"r600"},    GK_R600,    FEATURE_NONE },
964   {{"rv630"},   {"r600"},    GK_R600,    FEATURE_NONE },
965   {{"rv635"},   {"r600"},    GK_R600,    FEATURE_NONE },
966   {{"r630"},    {"r630"},    GK_R630,    FEATURE_NONE },
967   {{"rs780"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
968   {{"rs880"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
969   {{"rv610"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
970   {{"rv620"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
971   {{"rv670"},   {"rv670"},   GK_RV670,   FEATURE_NONE },
972   {{"rv710"},   {"rv710"},   GK_RV710,   FEATURE_NONE },
973   {{"rv730"},   {"rv730"},   GK_RV730,   FEATURE_NONE },
974   {{"rv740"},   {"rv770"},   GK_RV770,   FEATURE_NONE },
975   {{"rv770"},   {"rv770"},   GK_RV770,   FEATURE_NONE },
976   {{"cedar"},   {"cedar"},   GK_CEDAR,   FEATURE_NONE },
977   {{"palm"},    {"cedar"},   GK_CEDAR,   FEATURE_NONE },
978   {{"cypress"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA  },
979   {{"hemlock"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA  },
980   {{"juniper"}, {"juniper"}, GK_JUNIPER, FEATURE_NONE },
981   {{"redwood"}, {"redwood"}, GK_REDWOOD, FEATURE_NONE },
982   {{"sumo"},    {"sumo"},    GK_SUMO,    FEATURE_NONE },
983   {{"sumo2"},   {"sumo"},    GK_SUMO,    FEATURE_NONE },
984   {{"barts"},   {"barts"},   GK_BARTS,   FEATURE_NONE },
985   {{"caicos"},  {"caicos"},  GK_CAICOS,  FEATURE_NONE },
986   {{"aruba"},   {"cayman"},  GK_CAYMAN,  FEATURE_FMA  },
987   {{"cayman"},  {"cayman"},  GK_CAYMAN,  FEATURE_FMA  },
988   {{"turks"},   {"turks"},   GK_TURKS,   FEATURE_NONE }
989 };
990 
991 // This table should be sorted by the value of GPUKind
992 // Don't bother listing the implicitly true features
993 constexpr GPUInfo AMDGCNGPUs[32] = {
994   // Name         Canonical    Kind        Features
995   //              Name
996   {{"gfx600"},    {"gfx600"},  GK_GFX600,  FEATURE_FAST_FMA_F32},
997   {{"tahiti"},    {"gfx600"},  GK_GFX600,  FEATURE_FAST_FMA_F32},
998   {{"gfx601"},    {"gfx601"},  GK_GFX601,  FEATURE_NONE},
999   {{"hainan"},    {"gfx601"},  GK_GFX601,  FEATURE_NONE},
1000   {{"oland"},     {"gfx601"},  GK_GFX601,  FEATURE_NONE},
1001   {{"pitcairn"},  {"gfx601"},  GK_GFX601,  FEATURE_NONE},
1002   {{"verde"},     {"gfx601"},  GK_GFX601,  FEATURE_NONE},
1003   {{"gfx700"},    {"gfx700"},  GK_GFX700,  FEATURE_NONE},
1004   {{"kaveri"},    {"gfx700"},  GK_GFX700,  FEATURE_NONE},
1005   {{"gfx701"},    {"gfx701"},  GK_GFX701,  FEATURE_FAST_FMA_F32},
1006   {{"hawaii"},    {"gfx701"},  GK_GFX701,  FEATURE_FAST_FMA_F32},
1007   {{"gfx702"},    {"gfx702"},  GK_GFX702,  FEATURE_FAST_FMA_F32},
1008   {{"gfx703"},    {"gfx703"},  GK_GFX703,  FEATURE_NONE},
1009   {{"kabini"},    {"gfx703"},  GK_GFX703,  FEATURE_NONE},
1010   {{"mullins"},   {"gfx703"},  GK_GFX703,  FEATURE_NONE},
1011   {{"gfx704"},    {"gfx704"},  GK_GFX704,  FEATURE_NONE},
1012   {{"bonaire"},   {"gfx704"},  GK_GFX704,  FEATURE_NONE},
1013   {{"gfx801"},    {"gfx801"},  GK_GFX801,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1014   {{"carrizo"},   {"gfx801"},  GK_GFX801,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1015   {{"gfx802"},    {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
1016   {{"iceland"},   {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
1017   {{"tonga"},     {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
1018   {{"gfx803"},    {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
1019   {{"fiji"},      {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
1020   {{"polaris10"}, {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
1021   {{"polaris11"}, {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
1022   {{"gfx810"},    {"gfx810"},  GK_GFX810,  FEATURE_FAST_DENORMAL_F32},
1023   {{"stoney"},    {"gfx810"},  GK_GFX810,  FEATURE_FAST_DENORMAL_F32},
1024   {{"gfx900"},    {"gfx900"},  GK_GFX900,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1025   {{"gfx902"},    {"gfx902"},  GK_GFX902,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1026   {{"gfx904"},    {"gfx904"},  GK_GFX904,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1027   {{"gfx906"},    {"gfx906"},  GK_GFX906,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
1028 };
1029 
1030 const GPUInfo *getArchEntry(AMDGPU::GPUKind AK, ArrayRef<GPUInfo> Table) {
1031   GPUInfo Search = { {""}, {""}, AK, AMDGPU::FEATURE_NONE };
1032 
1033   auto I = std::lower_bound(Table.begin(), Table.end(), Search,
1034     [](const GPUInfo &A, const GPUInfo &B) {
1035       return A.Kind < B.Kind;
1036     });
1037 
1038   if (I == Table.end())
1039     return nullptr;
1040   return I;
1041 }
1042 
1043 } // namespace
1044 
1045 StringRef llvm::AMDGPU::getArchNameAMDGCN(GPUKind AK) {
1046   if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
1047     return Entry->CanonicalName;
1048   return "";
1049 }
1050 
1051 StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
1052   if (const auto *Entry = getArchEntry(AK, R600GPUs))
1053     return Entry->CanonicalName;
1054   return "";
1055 }
1056 
1057 AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
1058   for (const auto C : AMDGCNGPUs) {
1059     if (CPU == C.Name)
1060       return C.Kind;
1061   }
1062 
1063   return AMDGPU::GPUKind::GK_NONE;
1064 }
1065 
1066 AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
1067   for (const auto C : R600GPUs) {
1068     if (CPU == C.Name)
1069       return C.Kind;
1070   }
1071 
1072   return AMDGPU::GPUKind::GK_NONE;
1073 }
1074 
1075 unsigned AMDGPU::getArchAttrAMDGCN(GPUKind AK) {
1076   if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
1077     return Entry->Features;
1078   return FEATURE_NONE;
1079 }
1080 
1081 unsigned AMDGPU::getArchAttrR600(GPUKind AK) {
1082   if (const auto *Entry = getArchEntry(AK, R600GPUs))
1083     return Entry->Features;
1084   return FEATURE_NONE;
1085 }
1086 
1087 void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values) {
1088   // XXX: Should this only report unique canonical names?
1089   for (const auto C : AMDGCNGPUs)
1090     Values.push_back(C.Name);
1091 }
1092 
1093 void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
1094   for (const auto C : R600GPUs)
1095     Values.push_back(C.Name);
1096 }
1097 
1098 AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
1099   if (GPU == "generic")
1100     return {7, 0, 0};
1101 
1102   AMDGPU::GPUKind AK = parseArchAMDGCN(GPU);
1103   if (AK == AMDGPU::GPUKind::GK_NONE)
1104     return {0, 0, 0};
1105 
1106   switch (AK) {
1107   case GK_GFX600: return {6, 0, 0};
1108   case GK_GFX601: return {6, 0, 1};
1109   case GK_GFX700: return {7, 0, 0};
1110   case GK_GFX701: return {7, 0, 1};
1111   case GK_GFX702: return {7, 0, 2};
1112   case GK_GFX703: return {7, 0, 3};
1113   case GK_GFX704: return {7, 0, 4};
1114   case GK_GFX801: return {8, 0, 1};
1115   case GK_GFX802: return {8, 0, 2};
1116   case GK_GFX803: return {8, 0, 3};
1117   case GK_GFX810: return {8, 1, 0};
1118   case GK_GFX900: return {9, 0, 0};
1119   case GK_GFX902: return {9, 0, 2};
1120   case GK_GFX904: return {9, 0, 4};
1121   case GK_GFX906: return {9, 0, 6};
1122   default:        return {0, 0, 0};
1123   }
1124 }
1125