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