LLVM 24.0.0git
AMDGPUTargetParser.cpp
Go to the documentation of this file.
1//===-- AMDGPUTargetParser - Parser for AMDGPU features ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a target parser to recognise AMDGPU hardware features.
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/ADT/Twine.h"
19#include <array>
20#include <cassert>
21
22using namespace llvm;
23using namespace AMDGPU;
24
25namespace {
26constexpr unsigned NumAMDGPUSubArches =
28
29// A legacy GPU name (e.g. "tahiti") mapped to the GPUKind it aliases.
30struct GPUNameAlias {
31 StringTable::Offset AltName;
32 GPUKind Kind;
33};
34
35// Per-GPU data for the AMDGCN GPUKinds, from the generated table below.
36struct GPUInfo {
37 StringTable::Offset Name;
38 Triple::SubArchType SubArch;
39 unsigned ArchFeatures;
40 AMDGPUFeatureBitset Features;
41 IsaVersion Version;
42 StringTable::Offset FamilyName;
43 StringTable::Offset BaseName; // The canonical device name for a variant.
44 uint8_t MaxWavesPerEU;
45 uint32_t MaxHWAddressableLocalMemorySize;
46 uint8_t LDSBankCount;
47};
48
49// Per-GPU data for the R600 GPUKinds.
50struct R600Info {
51 StringTable::Offset Name;
52 R600FeatureKind ArchFeatures;
53};
54
55#define GET_AMDGPU_NAME_TABLE
56#define GET_AMDGPU_GPU_TABLE
57#define GET_AMDGPU_GPU_ALIAS_TABLE
58#define GET_AMDGPU_MAJOR_SUBARCH
59#define GET_AMDGPU_SUBARCH_NAME
60#define GET_AMDGPU_FEATURE_NAME_TABLE
61#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
62
63#define GET_R600_NAME_TABLE
64#define GET_R600_GPU_TABLE
65#define GET_R600_GPU_ALIAS_TABLE
66#include "llvm/TargetParser/R600TargetParserDef.inc"
67
68// The string tables holding GPU-name-derived strings as offsets. R600 and
69// AMDGPU come from separate generated headers, each with its own pool.
70constexpr StringTable AMDGPUNameStrTab = AMDGPUNameTable;
71constexpr StringTable R600NameStrTab = R600NameTable;
72
73// Look up the GPUInfo row for an AMDGCN GPUKind, or nullptr for GK_NONE / a
74// non-AMDGCN (R600) kind.
75const GPUInfo *getAMDGPUInfo(GPUKind AK) {
76 if (AK < AMDGPUFirstGPUKind)
77 return nullptr;
78 unsigned Idx = AK - AMDGPUFirstGPUKind;
79 if (Idx >= std::size(AMDGPUGPUTable))
80 return nullptr;
81 return &AMDGPUGPUTable[Idx];
82}
83
84// Look up the R600Info row for an R600 GPUKind, or nullptr for a non-R600 kind.
85const R600Info *getR600Info(GPUKind AK) {
86 if (AK < R600FirstGPUKind)
87 return nullptr;
88 unsigned Idx = AK - R600FirstGPUKind;
89 if (Idx >= std::size(R600GPUTable))
90 return nullptr;
91 return &R600GPUTable[Idx];
92}
93
94// Scan a name -> GPUKind table (canonical names, then aliases) for \p CPU.
95template <typename InfoT, size_t N, size_t M>
96GPUKind parseArchImpl(StringRef CPU, const InfoT (&Table)[N], GPUKind FirstKind,
97 const StringTable &StrTab,
98 const GPUNameAlias (&Aliases)[M]) {
99 for (unsigned I = 0; I != N; ++I) {
100 if (CPU == StrTab[Table[I].Name])
101 return static_cast<GPUKind>(FirstKind + I);
102 }
103
104 for (const GPUNameAlias &A : Aliases) {
105 if (CPU == StrTab[A.AltName])
106 return A.Kind;
107 }
108
109 return GK_NONE;
110}
111
112// Reverse map: SubArch -> GPUKind, indexed by (SubArch - FirstAMDGPUSubArch).
113// Subarches with no GPU (incl. the NoSubArch pseudo targets) map to GK_NONE.
114constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
115 std::array<GPUKind, NumAMDGPUSubArches> Map{};
116
117 for (unsigned I = 0; I < std::size(AMDGPUGPUTable); ++I) {
118 Triple::SubArchType SubArch = AMDGPUGPUTable[I].SubArch;
119 if (SubArch != Triple::NoSubArch) {
121 static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
122 }
123 }
124 return Map;
125}();
126
127/// SubArch -> major-family, indexed by (SubArch - FirstAMDGPUSubArch).
128constexpr std::array<Triple::SubArchType, NumAMDGPUSubArches>
129 AMDGPUMajorFamilies = [] {
130 std::array<Triple::SubArchType, NumAMDGPUSubArches> Map{};
131
132 for (unsigned I = 0; I < NumAMDGPUSubArches; ++I) {
133 Map[I] =
135 }
136
137 for (const AMDGPUMajorSubArchEntry &Entry : AMDGPUMajorSubArch)
138 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.Major;
139 return Map;
140 }();
141
142// SubArch -> name-offset, indexed by (SubArch - FirstAMDGPUSubArch). Unmapped
143// subarches keep offset 0 (the empty string).
144constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
145 AMDGPUSubArchNameOffsets = [] {
146 std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
147 for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
148 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.NameOffset;
149 return Map;
150 }();
151
152// SubArch -> triple-name-offset (e.g. "amdgpu9.00"), like
153// AMDGPUSubArchNameOffsets.
154constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
155 AMDGPUSubArchTripleNameOffsets = [] {
156 std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
157 for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
158 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] =
159 Entry.TripleNameOffset;
160 return Map;
161 }();
162} // namespace
163
165 const GPUInfo *Info = getAMDGPUInfo(AK);
166 return Info ? AMDGPUNameStrTab[Info->FamilyName] : "";
167}
168
170 const GPUInfo *Info = getAMDGPUInfo(AK);
171 return Info ? Info->SubArch : Triple::SubArchType::NoSubArch;
172}
173
177
179 const GPUInfo *Info = getAMDGPUInfo(AK);
180 return Info ? AMDGPUNameStrTab[Info->BaseName] : "";
181}
182
185 if (SubArch < Triple::FirstAMDGPUSubArch ||
187 return GK_NONE;
188 return AMDGPUSubArchToGPUKind[SubArch - Triple::FirstAMDGPUSubArch];
189}
190
196
198 if (A == B || A == Triple::NoSubArch || B == Triple::NoSubArch)
199 return true;
200
203
204 // One side is the major-family subarch covering the other's family.
205 if (A == MajorA)
206 return MajorA == MajorB;
207 if (B == MajorB)
208 return MajorA == MajorB;
209
210 return false;
211}
212
214 // An unrecognized GPU is never valid.
215 if (AK == GK_NONE)
216 return false;
217 // A legacy triple without a subarch accepts any known GPU.
218 if (SubArch == Triple::NoSubArch)
219 return true;
220
221 // Reject the dummy "generic" targets
222 Triple::SubArchType GPUSubArch = getSubArch(AK);
223 if (GPUSubArch == Triple::NoSubArch)
224 return false;
225
226 return isSubArchCompatible(GPUSubArch, SubArch);
227}
228
232
234 const GPUInfo *Info = getAMDGPUInfo(AK);
235 return Info && Info->SubArch == Triple::NoSubArch;
236}
237
241
243 // Tolerate subarch mismatch if one entry is none. This is a hack for bitcode
244 // libraries.
245 // There's a missing enum entry for an unknown subarch. Make sure the
246 // subarch is really empty.
247 if (A.getSubArch() == Triple::NoSubArch)
248 return A.getArchName().size() == 6;
249
250 if (B.getSubArch() == Triple::NoSubArch)
251 return B.getArchName().size() == 6;
252
253 return isSubArchCompatible(A.getSubArch(), B.getSubArch());
254}
255
256std::string AMDGPU::mergeSubArch(const Triple &A, const Triple &B) {
257 if (A.getSubArch() == Triple::NoSubArch)
258 return B.str();
259 if (B.getSubArch() == Triple::NoSubArch)
260 return A.str();
261
262 Triple::SubArchType MajorA = AMDGPU::getMajorSubArch(A.getSubArch());
263 Triple::SubArchType MajorB = AMDGPU::getMajorSubArch(B.getSubArch());
264
265 // With a compatible major arch, return the specific subarch.
266 if (A.getSubArch() == MajorA) {
267 if (MajorA == MajorB)
268 return B.str();
269 }
270
271 if (B.getSubArch() == MajorB) {
272 if (MajorA == MajorB)
273 return A.str();
274 }
275
276 // Invalid case.
277 return B.str();
278}
279
281 const GPUInfo *Info = getAMDGPUInfo(AK);
282 return Info ? AMDGPUNameStrTab[Info->Name] : "";
283}
284
286 if (SubArch < Triple::FirstAMDGPUSubArch ||
288 return "";
289 return AMDGPUNameStrTab[AMDGPUSubArchNameOffsets[SubArch -
291}
292
294 if (SubArch == Triple::NoSubArch)
295 return AMDGPUNameStrTab[AMDGPUNoSubArchNameOffset];
296
298 SubArch <= Triple::LastAMDGPUSubArch &&
299 "expected an AMDGPU subarch or NoSubArch");
300 return AMDGPUNameStrTab
301 [AMDGPUSubArchTripleNameOffsets[SubArch - Triple::FirstAMDGPUSubArch]];
302}
303
305 const R600Info *Info = getR600Info(AK);
306 return Info ? R600NameStrTab[Info->Name] : "";
307}
308
310 return parseArchImpl(CPU, AMDGPUGPUTable, AMDGPUFirstGPUKind,
311 AMDGPUNameStrTab, AMDGPUGPUAliases);
312}
313
315 return parseArchImpl(CPU, R600GPUTable, R600FirstGPUKind, R600NameStrTab,
316 R600GPUAliases);
317}
318
320 const GPUInfo *Info = getAMDGPUInfo(AK);
321 return Info ? Info->ArchFeatures : FEATURE_NONE;
322}
323
325 const GPUInfo *Info = getAMDGPUInfo(getGPUKindFromSubArch(SubArch));
326 return Info ? Info->ArchFeatures : FEATURE_NONE;
327}
328
330 const R600Info *Info = getR600Info(AK);
331 return Info ? Info->ArchFeatures : R600_FEATURE_NONE;
332}
333
335 static constexpr AMDGPUFeatureBitset Empty{};
336 const GPUInfo *Info = getAMDGPUInfo(AK);
337 return Info ? Info->Features : Empty;
338}
339
342 for (unsigned I = 0; I != NUM_FEATURES; ++I) {
343 if (Features.test(I))
344 Names.push_back(AMDGPUNameStrTab[AMDGPUFeatureNames[I]]);
345 }
346}
347
349 Triple::SubArchType SubArch) {
350 // XXX: Should this only report unique canonical names?
351 // An alias shares its GPU's GPUKind, so it is filtered alongside it.
352 for (unsigned I = 0; I != std::size(AMDGPUGPUTable); ++I) {
353 GPUKind Kind = static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
354 if (AMDGPUGPUTable[I].SubArch != Triple::NoSubArch &&
355 isCPUValidForSubArch(SubArch, Kind))
356 Values.push_back(AMDGPUNameStrTab[AMDGPUGPUTable[I].Name]);
357 }
358
359 for (const GPUNameAlias &A : AMDGPUGPUAliases) {
360 if (isCPUValidForSubArch(SubArch, A.Kind))
361 Values.push_back(AMDGPUNameStrTab[A.AltName]);
362 }
363}
364
366 for (const R600Info &Info : R600GPUTable)
367 Values.push_back(R600NameStrTab[Info.Name]);
368 for (const GPUNameAlias &A : R600GPUAliases)
369 Values.push_back(R600NameStrTab[A.AltName]);
370}
371
373 const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(GPU));
374 return Info ? Info->Version : IsaVersion{0, 0, 0};
375}
376
378 const GPUInfo *Info = getAMDGPUInfo(getGPUKindFromSubArch(SubArch));
379 return Info ? Info->Version : IsaVersion{0, 0, 0};
380}
381
384 if (Version.Major >= 8)
385 return 800;
386 return 512;
387}
388
391 if (Version.Major >= 8)
392 return 800;
393 return 512;
394}
395
397 if (getFeatureBitset(AK).test(FEAT_SGPR_INIT_BUG))
399
401 if (Version.Major >= 10)
402 return 106;
403 if (Version.Major >= 8)
404 return 102;
405 return 104;
406}
407
409 if (getFeatureBitset(getGPUKindFromSubArch(SubArch)).test(FEAT_SGPR_INIT_BUG))
411
413 if (Version.Major >= 10)
414 return 106;
415 if (Version.Major >= 8)
416 return 102;
417 return 104;
418}
419
422 if (Version.Major >= 10)
423 return getAddressableNumSGPRs(AK);
424 if (Version.Major >= 8)
425 return 16;
426 return 8;
427}
428
431 if (Version.Major >= 10)
432 return getAddressableNumSGPRs(SubArch);
433 if (Version.Major >= 8)
434 return 16;
435 return 8;
436}
437
438unsigned AMDGPU::getVGPRAllocGranule(GPUKind AK, bool IsWave32) {
439 const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
440 if (Features.test(FEAT_GFX90A_INSTS))
441 return 8;
442 if (Features.test(FEAT_1536_PHYSICAL_VGPRS))
443 return IsWave32 ? 24 : 12;
444 if (Features.test(FEAT_GFX10_3_INSTS))
445 return IsWave32 ? 16 : 8;
446 return IsWave32 ? 8 : 4;
447}
448
450 bool IsWave32) {
451 return getVGPRAllocGranule(getGPUKindFromSubArch(SubArch), IsWave32);
452}
453
455 const GPUInfo *Info = getAMDGPUInfo(AK);
456 return Info ? Info->MaxHWAddressableLocalMemorySize : 32768;
457}
458
459unsigned
463
465 const GPUInfo *Info = getAMDGPUInfo(AK);
466 return Info ? Info->LDSBankCount : 32;
467}
468
472
474 const GPUInfo *Info = getAMDGPUInfo(AK);
475 return Info ? Info->MaxWavesPerEU : 10;
476}
477
481
483 assert(T.isAMDGPU());
484 auto ProcKind = T.isAMDGCN() ? parseArchAMDGCN(Arch) : parseArchR600(Arch);
485 if (ProcKind == GK_NONE)
486 return StringRef();
487
488 return T.isAMDGCN() ? getArchNameAMDGCN(ProcKind) : getArchNameR600(ProcKind);
489}
490
491// Capability features clang queries via the feature bitset but must not
492// serialize into the target-feature string.
493//
494// FIXME: This is hacky, we shouldn't have mismatches between the bitset and
495// feature string map.
497 FEAT_FAST_FMAF, FEAT_FAST_DENORMAL_F32,
498 FEAT_SUPPORTS_WAVE32, FEAT_SUPPORTS_WGP,
499 FEAT_XNACK_SUPPORT, FEAT_SRAMECC_SUPPORT,
500 FEAT_XNACK_ON_OFF_MODES, FEAT_APERTURE_REGS,
501 FEAT_GET_DOORBELL_ID, FEAT_AGPR_ALLOC,
502 FEAT_1536_PHYSICAL_VGPRS, FEAT_HALF_ADDRESSABLE_PHYSICAL_LOCAL_MEMORY};
503
504// Add a GPU's features (minus the frontend-only ones) to \p Features. With \p
505// Overwrite false, existing entries are kept so user -mattr overrides win.
506static void addGPUFeatures(const GPUInfo &Info, bool Overwrite,
507 StringMap<bool> &Features) {
509 getFeatureNames(Info.Features & ~FrontendOnlyFeatures, Names);
510 for (StringRef Name : Names) {
511 if (Overwrite)
512 Features[Name] = true;
513 else
514 Features.insert({Name, true});
515 }
516}
517
518/// Add a GPU's default features to \p Features (preserving user overrides) and
519/// validate any requested wavesize.
520static std::pair<FeatureError, StringRef>
522 StringMap<bool> &Features) {
523 // With no explicit GPU, the triple's subarch identifies the target.
524 GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch
525 ? getGPUKindFromSubArch(T.getSubArch())
526 : parseArchAMDGCN(GPU);
527 const GPUInfo *Info = getAMDGPUInfo(Kind);
528
529 // A bare subarch triple (no -target-cpu) still pins down the target, so it is
530 // not a null GPU. The target's native wavesize (if single-mode) is in the
531 // feature bitset; a dual-mode GPU has neither wave bit set.
532 const bool IsNullGPU = T.getSubArch() == Triple::NoSubArch && GPU.empty();
533 const bool TargetHasWave32 =
534 Info && Info->Features.test(FEAT_WAVEFRONTSIZE32);
535 const bool TargetHasWave64 =
536 Info && Info->Features.test(FEAT_WAVEFRONTSIZE64);
537
538 auto Wave32Itr = Features.find("wavefrontsize32");
539 auto Wave64Itr = Features.find("wavefrontsize64");
540 const bool EnableWave32 =
541 Wave32Itr != Features.end() && Wave32Itr->getValue();
542 const bool EnableWave64 =
543 Wave64Itr != Features.end() && Wave64Itr->getValue();
544 const bool DisableWave32 =
545 Wave32Itr != Features.end() && !Wave32Itr->getValue();
546 const bool DisableWave64 =
547 Wave64Itr != Features.end() && !Wave64Itr->getValue();
548
549 if (EnableWave32 && EnableWave64)
551 "'+wavefrontsize32' and '+wavefrontsize64' are mutually exclusive"};
552 if (DisableWave32 && DisableWave64)
554 "'-wavefrontsize32' and '-wavefrontsize64' are mutually exclusive"};
555
556 if (!IsNullGPU) {
557 if (TargetHasWave64) {
558 if (EnableWave32)
559 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize32"};
560 if (DisableWave64)
561 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize64"};
562 }
563
564 if (TargetHasWave32) {
565 if (EnableWave64)
566 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize64"};
567 if (DisableWave32)
568 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize32"};
569 }
570 }
571
572 // Don't assume any wavesize with an unknown subtarget.
573 // Default to wave32 if target supports both.
574 if (!IsNullGPU && !EnableWave32 && !EnableWave64 && !TargetHasWave32 &&
575 !TargetHasWave64)
576 Features.insert({"wavefrontsize32", true});
577
578 // Merge the target defaults, keeping any user -mattr overrides.
579 if (Info)
580 addGPUFeatures(*Info, /*Overwrite=*/false, Features);
581
582 return {NO_ERROR, StringRef()};
583}
584
585/// Fills Features map with default values for given target GPU.
586/// \p Features contains overriding target features and this function returns
587/// default target features with entries overridden by \p Features.
588std::pair<FeatureError, StringRef>
590 StringMap<bool> &Features) {
591 // XXX - What does the member GPU mean if device name string passed here?
592 if (T.isSPIRV() && T.getOS() == Triple::OSType::AMDHSA) {
593 // AMDGCN SPIRV must support the union of all AMDGCN features.
596 for (StringRef G : GPUs)
597 if (const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(G)))
598 addGPUFeatures(*Info, /*Overwrite=*/true, Features);
599 Features["wavefrontsize32"] = true;
600 Features["wavefrontsize64"] = true;
601 } else if (T.isAMDGCN()) {
602 return fillAMDGCNFeatureMap(GPU, T, Features);
603 } else {
604 if (GPU.empty())
605 GPU = "r600";
606
607 switch (llvm::AMDGPU::parseArchR600(GPU)) {
608 case GK_CAYMAN:
609 case GK_CYPRESS:
610 case GK_RV770:
611 case GK_RV670:
612 // TODO: Add fp64 when implemented.
613 break;
614 case GK_TURKS:
615 case GK_CAICOS:
616 case GK_BARTS:
617 case GK_SUMO:
618 case GK_REDWOOD:
619 case GK_JUNIPER:
620 case GK_CEDAR:
621 case GK_RV730:
622 case GK_RV710:
623 case GK_RS880:
624 case GK_R630:
625 case GK_R600:
626 break;
627 default:
628 llvm_unreachable("Unhandled GPU!");
629 }
630 }
631 return {NO_ERROR, StringRef()};
632}
633
634TargetID::TargetID(GPUKind Arch, const Triple &TT, TargetIDSetting XnackSetting,
635 TargetIDSetting SramEccSetting)
636 : Arch(Arch),
637 TargetTripleString(TT.normalize(Triple::CanonicalForm::FOUR_IDENT)),
638 XnackSetting(XnackSetting), SramEccSetting(SramEccSetting),
639 IsAMDHSA(TT.getOS() == Triple::AMDHSA) {}
640
641// Parse a feature modifier sign ("+"/"-"). Returns "Unsupported" if \p Sign is
642// neither (i.e. the modifier is malformed).
644 if (Sign == "+")
645 return TargetIDSetting::On;
646 if (Sign == "-")
647 return TargetIDSetting::Off;
648
649 return TargetIDSetting::Unsupported;
650}
651
652// Derive the architecture from the processor name in \p TargetIDStr. "generic"
653// and the empty processor name act as a wildcard.
654static GPUKind getGPUKindFromTargetID(const Triple &TT, StringRef TargetIDStr) {
655 StringRef CPUName = TargetIDStr.split(':').first;
656 return (CPUName.empty() || CPUName == "generic")
657 ? getGPUKindFromSubArch(TT.getSubArch())
658 : parseArchAMDGCN(CPUName);
659}
660
661// Compute the xnack/sramecc settings for processor \p Arch from the
662// processor+features string \p TargetIDStr
663// (e.g. "gfx90a:xnack+:sramecc-"). Returns false if a modifier names an unknown
664// or repeated feature, names one the processor does not support, or has a
665// malformed sign.
666static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
669 const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
670 XnackSetting = Features.test(FEAT_XNACK_ON_OFF_MODES)
671 ? TargetIDSetting::Any
672 : TargetIDSetting::Unsupported;
673 SramEccSetting = Features.test(FEAT_SRAMECC_SUPPORT)
674 ? TargetIDSetting::Any
675 : TargetIDSetting::Unsupported;
676
677 // The first component is the processor; the rest are feature modifiers of the
678 // form "<feature><+|->".
680 TargetIDStr.split(Split, ':');
681 bool SeenXnack = false;
682 bool SeenSramEcc = false;
683 bool Valid = true;
684 for (unsigned I = 1, E = Split.size(); I != E; ++I) {
685 StringRef FeatureString = Split[I];
686 if (FeatureString.consume_front("xnack")) {
688 if (SeenXnack || XnackSetting == TargetIDSetting::Unsupported ||
689 Sign == TargetIDSetting::Unsupported)
690 Valid = false;
691 else
692 XnackSetting = Sign;
693 SeenXnack = true;
694 } else if (FeatureString.consume_front("sramecc")) {
696 if (SeenSramEcc || SramEccSetting == TargetIDSetting::Unsupported ||
697 Sign == TargetIDSetting::Unsupported)
698 Valid = false;
699 else
700 SramEccSetting = Sign;
701 SeenSramEcc = true;
702 } else {
703 // Unknown feature name.
704 Valid = false;
705 }
706 }
707 return Valid;
708}
709
710TargetID::TargetID(const Triple &TT, StringRef TargetIDStr)
711 : TargetID(getGPUKindFromTargetID(TT, TargetIDStr), TT,
713 // Derive the feature settings from the string. Validity is not checked here;
714 // parseTargetIDString validates untrusted input.
715 computeTargetIDFeatures(Arch, TargetIDStr, XnackSetting, SramEccSetting);
716}
717
718std::optional<TargetID> TargetID::parse(const Triple &TT,
719 StringRef ProcAndFeatures) {
720 if (!TT.isAMDGCN())
721 return std::nullopt;
722
723 // Filter out unrecognized subarch suffixes.
724 if (TT.getSubArch() == Triple::NoSubArch && TT.getArchName() != "amdgcn")
725 return std::nullopt;
726
727 // A named processor (i.e. not the empty/generic wildcard, which is resolved
728 // from the triple's subarch) must be a recognized GPU that is consistent with
729 // the triple's subarch.
730 StringRef CPUName = ProcAndFeatures.split(':').first;
731 if (!CPUName.empty() && CPUName != "generic" &&
732 !isCPUValidForSubArch(TT.getSubArch(), CPUName))
733 return std::nullopt;
734
735 // Parse the processor and its feature modifiers, then construct directly from
736 // the resulting fields.
737 GPUKind Arch = getGPUKindFromTargetID(TT, ProcAndFeatures);
738 TargetIDSetting XnackSetting, SramEccSetting;
739 if (!computeTargetIDFeatures(Arch, ProcAndFeatures, XnackSetting,
740 SramEccSetting))
741 return std::nullopt;
742
743 return TargetID(Arch, TT, XnackSetting, SramEccSetting);
744}
745
746std::optional<TargetID>
748 // Split on '-' to get arch-vendor-os-environment-processor:features. There is
749 // a single dash separator after the 4-component triple, so the
750 // processor+features field must be present (even if empty).
752 TargetIDDirective.split(Parts, '-', /*MaxSplit=*/4);
753 if (Parts.size() < 5)
754 return std::nullopt;
755
756 return parse(Triple(Parts[0], Parts[1], Parts[2], Parts[3]), Parts[4]);
757}
758
759// Append the explicit (On/Off) sramecc/xnack feature modifiers in canonical
760// order, e.g. ":sramecc-:xnack+".
762 TargetIDSetting Xnack) {
763 if (SramEcc == TargetIDSetting::Off)
764 OS << ":sramecc-";
765 else if (SramEcc == TargetIDSetting::On)
766 OS << ":sramecc+";
767
768 if (Xnack == TargetIDSetting::Off)
769 OS << ":xnack-";
770 else if (Xnack == TargetIDSetting::On)
771 OS << ":xnack+";
772}
773
774void TargetID::print(raw_ostream &StreamRep) const {
775 StreamRep << TargetTripleString << '-' << getArchNameAMDGCN(Arch);
776
777 if (IsAMDHSA)
779}
780
781std::string TargetID::toString() const {
782 std::string Str;
783 raw_string_ostream OS(Str);
784 OS << *this;
785 return Str;
786}
787
792
794 std::string Str;
795 raw_string_ostream OS(Str);
797 return Str;
798}
799
801 return Arch == Other.Arch && XnackSetting == Other.XnackSetting &&
802 SramEccSetting == Other.SramEccSetting && IsAMDHSA == Other.IsAMDHSA &&
803 TargetTripleString == Other.TargetTripleString;
804}
805
807 TargetIDSetting Requested) {
808 return Provided == TargetIDSetting::Any ||
809 Provided == TargetIDSetting::Unsupported || Provided == Requested;
810}
811
813 // The processor and feature settings must match exactly
814 if (Arch != Other.Arch || XnackSetting != Other.XnackSetting ||
815 SramEccSetting != Other.SramEccSetting)
816 return false;
817
819 .isCompatibleWith(Triple(Other.getTargetTripleString()));
820}
821
823 // A major-family/generic processor (e.g. amdgpu9) provides for a specific
824 // member of its family (e.g. gfx900), but not the reverse. Otherwise the
825 // processors must match.
826 if (Arch != Other.Arch && Arch != GK_NONE && Other.Arch != GK_NONE) {
827 Triple::SubArchType ThisSubArch = getSubArch(Arch);
828 if (ThisSubArch != getMajorSubArch(ThisSubArch) ||
829 ThisSubArch != getMajorSubArch(getSubArch(Other.Arch)))
830 return false;
831 }
832
833 if (!featureProvidesFor(XnackSetting, Other.XnackSetting) ||
834 !featureProvidesFor(SramEccSetting, Other.SramEccSetting))
835 return false;
836
838 .isCompatibleWith(Triple(Other.getTargetTripleString()));
839}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > SramEccSetting("amdgpu-sramecc", cl::desc("Force amdgpu.sramecc for testing"), cl::ReallyHidden)
static cl::opt< bool > XnackSetting("amdgpu-xnack", cl::desc("Force amdgpu.xnack value for testing"), cl::ReallyHidden)
static GPUKind getGPUKindFromTargetID(const Triple &TT, StringRef TargetIDStr)
static std::pair< FeatureError, StringRef > fillAMDGCNFeatureMap(StringRef GPU, const Triple &T, StringMap< bool > &Features)
Add a GPU's default features to Features (preserving user overrides) and validate any requested waves...
static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr, TargetIDSetting &XnackSetting, TargetIDSetting &SramEccSetting)
static TargetIDSetting getTargetIDSettingFromFeatureString(StringRef Sign)
static void printFeatureModifiers(raw_ostream &OS, TargetIDSetting SramEcc, TargetIDSetting Xnack)
static bool featureProvidesFor(TargetIDSetting Provided, TargetIDSetting Requested)
static void addGPUFeatures(const GPUInfo &Info, bool Overwrite, StringMap< bool > &Features)
static const AMDGPUFeatureBitset FrontendOnlyFeatures
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define T
modulo schedule test
This file defines the SmallVector class.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
void printCanonicalTargetIDString(raw_ostream &OS) const
Print the canonical processor name followed by any explicit xnack and sramecc feature modifiers (e....
static std::optional< TargetID > parseTargetIDString(StringRef TargetIDDirective)
Parse and validate a TargetID from a full "<triple>-<processor>:<features>" directive string.
void print(raw_ostream &OS) const
TargetIDSetting getXnackSetting() const
bool isEquivalent(const TargetID &Other) const
Returns true if Other denotes the same target as *this, i.e.
bool operator==(const TargetID &Other) const
bool providesFor(const TargetID &Other) const
Returns true if a device image for *this can provide the device code for a request for Other.
StringRef getTargetTripleString() const
std::string getCanonicalFeatureString() const
TargetID(GPUKind Arch, const Triple &TT, TargetIDSetting XnackSetting, TargetIDSetting SramEccSetting)
static std::optional< TargetID > parse(const Triple &TT, StringRef ProcAndFeatures)
Parse and validate a TargetID for triple TT from the processor+features string ProcAndFeatures (e....
std::string toString() const
TargetIDSetting getSramEccSetting() const
constexpr bool test(unsigned I) const
Definition Bitset.h:109
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:129
iterator end()
Definition StringMap.h:214
iterator find(StringRef Key)
Definition StringMap.h:227
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition StringMap.h:311
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
A table of densely packed, null-terminated strings indexed by offset.
Definition StringTable.h:34
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
@ FirstAMDGPUSubArch
Definition Triple.h:277
@ LastAMDGPUSubArch
Definition Triple.h:278
LLVM_ABI bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition Triple.cpp:2269
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getArchNameR600(GPUKind AK)
LLVM_ABI void fillValidArchListAMDGCN(SmallVectorImpl< StringRef > &Values, Triple::SubArchType SubArch=Triple::NoSubArch)
Append the valid AMDGCN GPU names to Values.
LLVM_ABI unsigned getMaxWavesPerEU(GPUKind AK)
LLVM_ABI StringRef getCanonicalArchName(const Triple &T, StringRef Arch)
LLVM_ABI StringRef getBaseArchNameAMDGCN(GPUKind AK)
The canonical GPU name for a variant name.
LLVM_ABI void fillValidArchListR600(SmallVectorImpl< StringRef > &Values)
LLVM_ABI R600FeatureKind getArchAttrR600(GPUKind AK)
LLVM_ABI std::string mergeSubArch(const Triple &A, const Triple &B)
Returns the effective triple appropriate to use when linking B into A by merging the subarches in cas...
LLVM_ABI bool isCPUValidForSubArch(Triple::SubArchType SubArch, GPUKind AK)
Return true if the GPU AK is usable with the triple subarch SubArch.
LLVM_ABI bool isSubArchCompatible(const Triple &A, const Triple &B)
Return true if subarch A is compatible with subarch B, i.e.
LLVM_ABI unsigned getLDSBankCount(GPUKind AK)
LLVM_ABI unsigned getMaxHWAddressableLocalMemorySize(GPUKind AK)
LLVM_ABI StringRef getArchFamilyNameAMDGCN(GPUKind AK)
LLVM_ABI StringRef getSubArchName(Triple::SubArchType SubArch)
Returns the triple subarch name for an AMDGPU subarch, e.g.
LLVM_ABI unsigned getAddressableNumSGPRs(GPUKind AK)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_ABI unsigned getTotalNumSGPRs(GPUKind AK)
GPUKind
GPU kinds supported by the AMDGPU target.
Bitset< NUM_FEATURES > AMDGPUFeatureBitset
LLVM_ABI Triple::SubArchType getSubArchFromGPUName(StringRef CPU)
Returns the preferred subarch for a GPU name CPU, or NoSubArch if unrecognized.
LLVM_ABI unsigned getSGPRAllocGranule(GPUKind AK)
LLVM_ABI Triple::SubArchType getSubArch(GPUKind AK)
LLVM_ABI StringRef getArchNameFromSubArch(Triple::SubArchType SubArch)
Returns the canonical GPU name for an AMDGPU subarch, e.g.
LLVM_ABI unsigned getVGPRAllocGranule(GPUKind AK, bool IsWave32)
LLVM_ABI GPUKind parseArchAMDGCN(StringRef CPU)
LLVM_ABI bool isPseudoTarget(GPUKind AK)
Return true if AK is a pseudo target (e.g.
LLVM_ABI GPUKind getGPUKindFromSubArch(Triple::SubArchType SubArch)
AMDGPU::TargetID TargetID
LLVM_ABI std::pair< FeatureError, StringRef > fillAMDGPUFeatureMap(StringRef GPU, const Triple &T, StringMap< bool > &Features)
Fills Features map with default values for given target GPU.
LLVM_ABI void getFeatureNames(const AMDGPUFeatureBitset &Features, SmallVectorImpl< StringRef > &Names)
Appends the feature name of each bit set in Features to Names.
LLVM_ABI StringRef getArchNameAMDGCN(GPUKind AK)
LLVM_ABI unsigned getArchAttrAMDGCN(GPUKind AK)
LLVM_ABI Triple::SubArchType getMajorSubArch(Triple::SubArchType SubArch)
LLVM_ABI const AMDGPUFeatureBitset & getFeatureBitset(GPUKind AK)
Returns AK's feature bitset, or an empty bitset if unknown.
LLVM_ABI GPUKind parseArchR600(StringRef CPU)
This is an optimization pass for GlobalISel generic memory operations.
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
#define N
Instruction set architecture version.