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
14#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/Twine.h"
20#include <array>
21#include <cassert>
22
23using namespace llvm;
24using namespace AMDGPU;
25
26namespace {
27constexpr unsigned NumAMDGPUSubArches =
29
30// A legacy GPU name (e.g. "tahiti") mapped to the GPUKind it aliases.
31struct GPUNameAlias {
32 StringTable::Offset AltName;
33 GPUKind Kind;
34};
35
36// Per-GPU data for the AMDGCN GPUKinds, from the generated table below.
37struct GPUInfo {
38 StringTable::Offset Name;
39 Triple::SubArchType SubArch;
40 unsigned ArchFeatures;
41 AMDGPUFeatureBitset Features;
42 IsaVersion Version;
43 StringTable::Offset FamilyName;
44};
45
46// Per-GPU data for the R600 GPUKinds.
47struct R600Info {
48 StringTable::Offset Name;
49 R600FeatureKind ArchFeatures;
50};
51
52#define GET_AMDGPU_NAME_TABLE
53#define GET_AMDGPU_GPU_TABLE
54#define GET_AMDGPU_GPU_ALIAS_TABLE
55#define GET_AMDGPU_MAJOR_SUBARCH
56#define GET_AMDGPU_SUBARCH_NAME
57#define GET_AMDGPU_FEATURE_NAME_TABLE
58#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
59
60#define GET_R600_NAME_TABLE
61#define GET_R600_GPU_TABLE
62#define GET_R600_GPU_ALIAS_TABLE
63#include "llvm/TargetParser/R600TargetParserDef.inc"
64
65// The string tables holding GPU-name-derived strings as offsets. R600 and
66// AMDGPU come from separate generated headers, each with its own pool.
67constexpr StringTable AMDGPUNameStrTab = AMDGPUNameTable;
68constexpr StringTable R600NameStrTab = R600NameTable;
69
70// Look up the GPUInfo row for an AMDGCN GPUKind, or nullptr for GK_NONE / a
71// non-AMDGCN (R600) kind.
72const GPUInfo *getAMDGPUInfo(GPUKind AK) {
73 if (AK < AMDGPUFirstGPUKind)
74 return nullptr;
75 unsigned Idx = AK - AMDGPUFirstGPUKind;
76 if (Idx >= std::size(AMDGPUGPUTable))
77 return nullptr;
78 return &AMDGPUGPUTable[Idx];
79}
80
81// Look up the R600Info row for an R600 GPUKind, or nullptr for a non-R600 kind.
82const R600Info *getR600Info(GPUKind AK) {
83 if (AK < R600FirstGPUKind)
84 return nullptr;
85 unsigned Idx = AK - R600FirstGPUKind;
86 if (Idx >= std::size(R600GPUTable))
87 return nullptr;
88 return &R600GPUTable[Idx];
89}
90
91// Scan a name -> GPUKind table (canonical names, then aliases) for \p CPU.
92template <typename InfoT, size_t N, size_t M>
93GPUKind parseArchImpl(StringRef CPU, const InfoT (&Table)[N], GPUKind FirstKind,
94 const StringTable &StrTab,
95 const GPUNameAlias (&Aliases)[M]) {
96 for (unsigned I = 0; I != N; ++I) {
97 if (CPU == StrTab[Table[I].Name])
98 return static_cast<GPUKind>(FirstKind + I);
99 }
100
101 for (const GPUNameAlias &A : Aliases) {
102 if (CPU == StrTab[A.AltName])
103 return A.Kind;
104 }
105
106 return GK_NONE;
107}
108
109// Reverse map: SubArch -> GPUKind, indexed by (SubArch - FirstAMDGPUSubArch).
110// Subarches with no GPU (incl. the NoSubArch pseudo targets) map to GK_NONE.
111constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
112 std::array<GPUKind, NumAMDGPUSubArches> Map{};
113
114 for (unsigned I = 0; I < std::size(AMDGPUGPUTable); ++I) {
115 Triple::SubArchType SubArch = AMDGPUGPUTable[I].SubArch;
116 if (SubArch != Triple::NoSubArch) {
118 static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
119 }
120 }
121 return Map;
122}();
123
124/// SubArch -> major-family, indexed by (SubArch - FirstAMDGPUSubArch).
125constexpr std::array<Triple::SubArchType, NumAMDGPUSubArches>
126 AMDGPUMajorFamilies = [] {
127 std::array<Triple::SubArchType, NumAMDGPUSubArches> Map{};
128
129 for (unsigned I = 0; I < NumAMDGPUSubArches; ++I) {
130 Map[I] =
132 }
133
134 for (const AMDGPUMajorSubArchEntry &Entry : AMDGPUMajorSubArch)
135 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.Major;
136 return Map;
137 }();
138
139// SubArch -> name-offset, indexed by (SubArch - FirstAMDGPUSubArch). Unmapped
140// subarches keep offset 0 (the empty string).
141constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
142 AMDGPUSubArchNameOffsets = [] {
143 std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
144 for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
145 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.NameOffset;
146 return Map;
147 }();
148
149// SubArch -> triple-name-offset (e.g. "amdgpu9.00"), like
150// AMDGPUSubArchNameOffsets.
151constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
152 AMDGPUSubArchTripleNameOffsets = [] {
153 std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
154 for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
155 Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] =
156 Entry.TripleNameOffset;
157 return Map;
158 }();
159} // namespace
160
162 const GPUInfo *Info = getAMDGPUInfo(AK);
163 return Info ? AMDGPUNameStrTab[Info->FamilyName] : "";
164}
165
167 const GPUInfo *Info = getAMDGPUInfo(AK);
168 return Info ? Info->SubArch : Triple::SubArchType::NoSubArch;
169}
170
173 if (SubArch < Triple::FirstAMDGPUSubArch ||
175 return GK_NONE;
176 return AMDGPUSubArchToGPUKind[SubArch - Triple::FirstAMDGPUSubArch];
177}
178
184
186 if (A == B || A == Triple::NoSubArch || B == Triple::NoSubArch)
187 return true;
188
191
192 // One side is the major-family subarch covering the other's family.
193 if (A == MajorA)
194 return MajorA == MajorB;
195 if (B == MajorB)
196 return MajorA == MajorB;
197
198 return false;
199}
200
202 // An unrecognized GPU is never valid.
203 if (AK == GK_NONE)
204 return false;
205 // A legacy triple without a subarch accepts any known GPU.
206 if (SubArch == Triple::NoSubArch)
207 return true;
208
209 // Reject the dummy "generic" targets
210 Triple::SubArchType GPUSubArch = getSubArch(AK);
211 if (GPUSubArch == Triple::NoSubArch)
212 return false;
213
214 return isSubArchCompatible(GPUSubArch, SubArch);
215}
216
220
222 const GPUInfo *Info = getAMDGPUInfo(AK);
223 return Info && Info->SubArch == Triple::NoSubArch;
224}
225
229
231 // Tolerate subarch mismatch if one entry is none. This is a hack for bitcode
232 // libraries.
233 // There's a missing enum entry for an unknown subarch. Make sure the
234 // subarch is really empty.
235 if (A.getSubArch() == Triple::NoSubArch)
236 return A.getArchName().size() == 6;
237
238 if (B.getSubArch() == Triple::NoSubArch)
239 return B.getArchName().size() == 6;
240
241 return isSubArchCompatible(A.getSubArch(), B.getSubArch());
242}
243
244std::string AMDGPU::mergeSubArch(const Triple &A, const Triple &B) {
245 if (A.getSubArch() == Triple::NoSubArch)
246 return B.str();
247 if (B.getSubArch() == Triple::NoSubArch)
248 return A.str();
249
250 Triple::SubArchType MajorA = AMDGPU::getMajorSubArch(A.getSubArch());
251 Triple::SubArchType MajorB = AMDGPU::getMajorSubArch(B.getSubArch());
252
253 // With a compatible major arch, return the specific subarch.
254 if (A.getSubArch() == MajorA) {
255 if (MajorA == MajorB)
256 return B.str();
257 }
258
259 if (B.getSubArch() == MajorB) {
260 if (MajorA == MajorB)
261 return A.str();
262 }
263
264 // Invalid case.
265 return B.str();
266}
267
269 const GPUInfo *Info = getAMDGPUInfo(AK);
270 return Info ? AMDGPUNameStrTab[Info->Name] : "";
271}
272
274 if (SubArch < Triple::FirstAMDGPUSubArch ||
276 return "";
277 return AMDGPUNameStrTab[AMDGPUSubArchNameOffsets[SubArch -
279}
280
282 if (SubArch == Triple::NoSubArch)
283 return AMDGPUNameStrTab[AMDGPUNoSubArchNameOffset];
284
286 SubArch <= Triple::LastAMDGPUSubArch &&
287 "expected an AMDGPU subarch or NoSubArch");
288 return AMDGPUNameStrTab
289 [AMDGPUSubArchTripleNameOffsets[SubArch - Triple::FirstAMDGPUSubArch]];
290}
291
293 const R600Info *Info = getR600Info(AK);
294 return Info ? R600NameStrTab[Info->Name] : "";
295}
296
298 return parseArchImpl(CPU, AMDGPUGPUTable, AMDGPUFirstGPUKind,
299 AMDGPUNameStrTab, AMDGPUGPUAliases);
300}
301
303 return parseArchImpl(CPU, R600GPUTable, R600FirstGPUKind, R600NameStrTab,
304 R600GPUAliases);
305}
306
308 const GPUInfo *Info = getAMDGPUInfo(AK);
309 return Info ? Info->ArchFeatures : FEATURE_NONE;
310}
311
315
317 const R600Info *Info = getR600Info(AK);
318 return Info ? Info->ArchFeatures : R600_FEATURE_NONE;
319}
320
322 static constexpr AMDGPUFeatureBitset Empty{};
323 const GPUInfo *Info = getAMDGPUInfo(AK);
324 return Info ? Info->Features : Empty;
325}
326
329 for (unsigned I = 0; I != NUM_FEATURES; ++I) {
330 if (Features.test(I))
331 Names.push_back(AMDGPUNameStrTab[AMDGPUFeatureNames[I]]);
332 }
333}
334
336 Triple::SubArchType SubArch) {
337 // XXX: Should this only report unique canonical names?
338 // An alias shares its GPU's GPUKind, so it is filtered alongside it.
339 for (unsigned I = 0; I != std::size(AMDGPUGPUTable); ++I) {
340 GPUKind Kind = static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
341 if (AMDGPUGPUTable[I].SubArch != Triple::NoSubArch &&
342 isCPUValidForSubArch(SubArch, Kind))
343 Values.push_back(AMDGPUNameStrTab[AMDGPUGPUTable[I].Name]);
344 }
345
346 for (const GPUNameAlias &A : AMDGPUGPUAliases) {
347 if (isCPUValidForSubArch(SubArch, A.Kind))
348 Values.push_back(AMDGPUNameStrTab[A.AltName]);
349 }
350}
351
353 for (const R600Info &Info : R600GPUTable)
354 Values.push_back(R600NameStrTab[Info.Name]);
355 for (const GPUNameAlias &A : R600GPUAliases)
356 Values.push_back(R600NameStrTab[A.AltName]);
357}
358
360 const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(GPU));
361 return Info ? Info->Version : IsaVersion{0, 0, 0};
362}
363
365 const GPUInfo *Info = getAMDGPUInfo(getGPUKindFromSubArch(SubArch));
366 return Info ? Info->Version : IsaVersion{0, 0, 0};
367}
368
371 if (Version.Major >= 8)
372 return 800;
373 return 512;
374}
375
378 if (Version.Major >= 8)
379 return 800;
380 return 512;
381}
382
386
388 if (Version.Major >= 10)
389 return 106;
390 if (Version.Major >= 8)
391 return 102;
392 return 104;
393}
394
398
400 if (Version.Major >= 10)
401 return 106;
402 if (Version.Major >= 8)
403 return 102;
404 return 104;
405}
406
409 if (Version.Major >= 10)
410 return getAddressableNumSGPRs(AK);
411 if (Version.Major >= 8)
412 return 16;
413 return 8;
414}
415
418 if (Version.Major >= 10)
419 return getAddressableNumSGPRs(SubArch);
420 if (Version.Major >= 8)
421 return 16;
422 return 8;
423}
424
426 assert(T.isAMDGPU());
427 auto ProcKind = T.isAMDGCN() ? parseArchAMDGCN(Arch) : parseArchR600(Arch);
428 if (ProcKind == GK_NONE)
429 return StringRef();
430
431 return T.isAMDGCN() ? getArchNameAMDGCN(ProcKind) : getArchNameR600(ProcKind);
432}
433
434// Add each frontend feature in \p Info's bitset to \p Features. With \p
435// Overwrite false, existing entries are kept so user -mattr overrides win.
436static void addGPUFeatures(const GPUInfo &Info, bool Overwrite,
437 StringMap<bool> &Features) {
439 getFeatureNames(Info.Features, Names);
440 for (StringRef Name : Names) {
441 if (Overwrite)
442 Features[Name] = true;
443 else
444 Features.insert({Name, true});
445 }
446}
447
448/// Add a GPU's default features to \p Features (preserving user overrides) and
449/// validate any requested wavesize.
450static std::pair<FeatureError, StringRef>
452 StringMap<bool> &Features) {
453 // With no explicit GPU, the triple's subarch identifies the target.
454 GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch
455 ? getGPUKindFromSubArch(T.getSubArch())
456 : parseArchAMDGCN(GPU);
457 const GPUInfo *Info = getAMDGPUInfo(Kind);
458
459 // A bare subarch triple (no -target-cpu) still pins down the target, so it is
460 // not a null GPU. The target's native wavesize (if single-mode) is in the
461 // feature bitset; a dual-mode GPU has neither wave bit set.
462 const bool IsNullGPU = T.getSubArch() == Triple::NoSubArch && GPU.empty();
463 const bool TargetHasWave32 =
464 Info && Info->Features.test(FEAT_WAVEFRONTSIZE32);
465 const bool TargetHasWave64 =
466 Info && Info->Features.test(FEAT_WAVEFRONTSIZE64);
467
468 auto Wave32Itr = Features.find("wavefrontsize32");
469 auto Wave64Itr = Features.find("wavefrontsize64");
470 const bool EnableWave32 =
471 Wave32Itr != Features.end() && Wave32Itr->getValue();
472 const bool EnableWave64 =
473 Wave64Itr != Features.end() && Wave64Itr->getValue();
474 const bool DisableWave32 =
475 Wave32Itr != Features.end() && !Wave32Itr->getValue();
476 const bool DisableWave64 =
477 Wave64Itr != Features.end() && !Wave64Itr->getValue();
478
479 if (EnableWave32 && EnableWave64)
481 "'+wavefrontsize32' and '+wavefrontsize64' are mutually exclusive"};
482 if (DisableWave32 && DisableWave64)
484 "'-wavefrontsize32' and '-wavefrontsize64' are mutually exclusive"};
485
486 if (!IsNullGPU) {
487 if (TargetHasWave64) {
488 if (EnableWave32)
489 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize32"};
490 if (DisableWave64)
491 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize64"};
492 }
493
494 if (TargetHasWave32) {
495 if (EnableWave64)
496 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize64"};
497 if (DisableWave32)
498 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize32"};
499 }
500 }
501
502 // Don't assume any wavesize with an unknown subtarget.
503 // Default to wave32 if target supports both.
504 if (!IsNullGPU && !EnableWave32 && !EnableWave64 && !TargetHasWave32 &&
505 !TargetHasWave64)
506 Features.insert({"wavefrontsize32", true});
507
508 // Merge the target defaults, keeping any user -mattr overrides.
509 if (Info)
510 addGPUFeatures(*Info, /*Overwrite=*/false, Features);
511
512 return {NO_ERROR, StringRef()};
513}
514
515/// Fills Features map with default values for given target GPU.
516/// \p Features contains overriding target features and this function returns
517/// default target features with entries overridden by \p Features.
518std::pair<FeatureError, StringRef>
520 StringMap<bool> &Features) {
521 // XXX - What does the member GPU mean if device name string passed here?
522 if (T.isSPIRV() && T.getOS() == Triple::OSType::AMDHSA) {
523 // AMDGCN SPIRV must support the union of all AMDGCN features.
526 for (StringRef G : GPUs)
527 if (const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(G)))
528 addGPUFeatures(*Info, /*Overwrite=*/true, Features);
529 Features["wavefrontsize32"] = true;
530 Features["wavefrontsize64"] = true;
531 } else if (T.isAMDGCN()) {
532 return fillAMDGCNFeatureMap(GPU, T, Features);
533 } else {
534 if (GPU.empty())
535 GPU = "r600";
536
537 switch (llvm::AMDGPU::parseArchR600(GPU)) {
538 case GK_CAYMAN:
539 case GK_CYPRESS:
540 case GK_RV770:
541 case GK_RV670:
542 // TODO: Add fp64 when implemented.
543 break;
544 case GK_TURKS:
545 case GK_CAICOS:
546 case GK_BARTS:
547 case GK_SUMO:
548 case GK_REDWOOD:
549 case GK_JUNIPER:
550 case GK_CEDAR:
551 case GK_RV730:
552 case GK_RV710:
553 case GK_RS880:
554 case GK_R630:
555 case GK_R600:
556 break;
557 default:
558 llvm_unreachable("Unhandled GPU!");
559 }
560 }
561 return {NO_ERROR, StringRef()};
562}
563
564TargetID::TargetID(GPUKind Arch, const Triple &TT, TargetIDSetting XnackSetting,
565 TargetIDSetting SramEccSetting)
566 : Arch(Arch),
567 TargetTripleString(TT.normalize(Triple::CanonicalForm::FOUR_IDENT)),
568 XnackSetting(XnackSetting), SramEccSetting(SramEccSetting),
569 IsAMDHSA(TT.getOS() == Triple::AMDHSA) {}
570
571// Parse a feature modifier sign ("+"/"-"). Returns "Unsupported" if \p Sign is
572// neither (i.e. the modifier is malformed).
574 if (Sign == "+")
575 return TargetIDSetting::On;
576 if (Sign == "-")
577 return TargetIDSetting::Off;
578
579 return TargetIDSetting::Unsupported;
580}
581
582// Derive the architecture from the processor name in \p TargetIDStr. "generic"
583// and the empty processor name act as a wildcard.
584static GPUKind getGPUKindFromTargetID(const Triple &TT, StringRef TargetIDStr) {
585 StringRef CPUName = TargetIDStr.split(':').first;
586 return (CPUName.empty() || CPUName == "generic")
587 ? getGPUKindFromSubArch(TT.getSubArch())
588 : parseArchAMDGCN(CPUName);
589}
590
591// Compute the xnack/sramecc settings for processor \p Arch from the
592// processor+features string \p TargetIDStr
593// (e.g. "gfx90a:xnack+:sramecc-"). Returns false if a modifier names an unknown
594// or repeated feature, names one the processor does not support, or has a
595// malformed sign.
596static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
599 unsigned ArchAttr = getArchAttrAMDGCN(Arch);
601 ? TargetIDSetting::Any
602 : TargetIDSetting::Unsupported;
603 SramEccSetting = (ArchAttr & FEATURE_SRAMECC) ? TargetIDSetting::Any
604 : TargetIDSetting::Unsupported;
605
606 // The first component is the processor; the rest are feature modifiers of the
607 // form "<feature><+|->".
609 TargetIDStr.split(Split, ':');
610 bool SeenXnack = false;
611 bool SeenSramEcc = false;
612 bool Valid = true;
613 for (unsigned I = 1, E = Split.size(); I != E; ++I) {
614 StringRef FeatureString = Split[I];
615 if (FeatureString.consume_front("xnack")) {
617 if (SeenXnack || XnackSetting == TargetIDSetting::Unsupported ||
618 Sign == TargetIDSetting::Unsupported)
619 Valid = false;
620 else
621 XnackSetting = Sign;
622 SeenXnack = true;
623 } else if (FeatureString.consume_front("sramecc")) {
625 if (SeenSramEcc || SramEccSetting == TargetIDSetting::Unsupported ||
626 Sign == TargetIDSetting::Unsupported)
627 Valid = false;
628 else
629 SramEccSetting = Sign;
630 SeenSramEcc = true;
631 } else {
632 // Unknown feature name.
633 Valid = false;
634 }
635 }
636 return Valid;
637}
638
639TargetID::TargetID(const Triple &TT, StringRef TargetIDStr)
640 : TargetID(getGPUKindFromTargetID(TT, TargetIDStr), TT,
642 // Derive the feature settings from the string. Validity is not checked here;
643 // parseTargetIDString validates untrusted input.
644 computeTargetIDFeatures(Arch, TargetIDStr, XnackSetting, SramEccSetting);
645}
646
647std::optional<TargetID> TargetID::parse(const Triple &TT,
648 StringRef ProcAndFeatures) {
649 if (!TT.isAMDGCN())
650 return std::nullopt;
651
652 // Filter out unrecognized subarch suffixes.
653 if (TT.getSubArch() == Triple::NoSubArch && TT.getArchName() != "amdgcn")
654 return std::nullopt;
655
656 // A named processor (i.e. not the empty/generic wildcard, which is resolved
657 // from the triple's subarch) must be a recognized GPU that is consistent with
658 // the triple's subarch.
659 StringRef CPUName = ProcAndFeatures.split(':').first;
660 if (!CPUName.empty() && CPUName != "generic" &&
661 !isCPUValidForSubArch(TT.getSubArch(), CPUName))
662 return std::nullopt;
663
664 // Parse the processor and its feature modifiers, then construct directly from
665 // the resulting fields.
666 GPUKind Arch = getGPUKindFromTargetID(TT, ProcAndFeatures);
667 TargetIDSetting XnackSetting, SramEccSetting;
668 if (!computeTargetIDFeatures(Arch, ProcAndFeatures, XnackSetting,
669 SramEccSetting))
670 return std::nullopt;
671
672 return TargetID(Arch, TT, XnackSetting, SramEccSetting);
673}
674
675std::optional<TargetID>
677 // Split on '-' to get arch-vendor-os-environment-processor:features. There is
678 // a single dash separator after the 4-component triple, so the
679 // processor+features field must be present (even if empty).
681 TargetIDDirective.split(Parts, '-', /*MaxSplit=*/4);
682 if (Parts.size() < 5)
683 return std::nullopt;
684
685 return parse(Triple(Parts[0], Parts[1], Parts[2], Parts[3]), Parts[4]);
686}
687
688// Append the explicit (On/Off) sramecc/xnack feature modifiers in canonical
689// order, e.g. ":sramecc-:xnack+".
691 TargetIDSetting Xnack) {
692 if (SramEcc == TargetIDSetting::Off)
693 OS << ":sramecc-";
694 else if (SramEcc == TargetIDSetting::On)
695 OS << ":sramecc+";
696
697 if (Xnack == TargetIDSetting::Off)
698 OS << ":xnack-";
699 else if (Xnack == TargetIDSetting::On)
700 OS << ":xnack+";
701}
702
703void TargetID::print(raw_ostream &StreamRep) const {
704 StreamRep << TargetTripleString << '-' << getArchNameAMDGCN(Arch);
705
706 if (IsAMDHSA)
708}
709
710std::string TargetID::toString() const {
711 std::string Str;
712 raw_string_ostream OS(Str);
713 OS << *this;
714 return Str;
715}
716
721
723 std::string Str;
724 raw_string_ostream OS(Str);
726 return Str;
727}
728
730 return Arch == Other.Arch && XnackSetting == Other.XnackSetting &&
731 SramEccSetting == Other.SramEccSetting && IsAMDHSA == Other.IsAMDHSA &&
732 TargetTripleString == Other.TargetTripleString;
733}
734
736 TargetIDSetting Requested) {
737 return Provided == TargetIDSetting::Any ||
738 Provided == TargetIDSetting::Unsupported || Provided == Requested;
739}
740
742 // The processor and feature settings must match exactly
743 if (Arch != Other.Arch || XnackSetting != Other.XnackSetting ||
744 SramEccSetting != Other.SramEccSetting)
745 return false;
746
748 .isCompatibleWith(Triple(Other.getTargetTripleString()));
749}
750
752 // A major-family/generic processor (e.g. amdgpu9) provides for a specific
753 // member of its family (e.g. gfx900), but not the reverse. Otherwise the
754 // processors must match.
755 if (Arch != Other.Arch && Arch != GK_NONE && Other.Arch != GK_NONE) {
756 Triple::SubArchType ThisSubArch = getSubArch(Arch);
757 if (ThisSubArch != getMajorSubArch(ThisSubArch) ||
758 ThisSubArch != getMajorSubArch(getSubArch(Other.Arch)))
759 return false;
760 }
761
762 if (!featureProvidesFor(XnackSetting, Other.XnackSetting) ||
763 !featureProvidesFor(SramEccSetting, Other.SramEccSetting))
764 return false;
765
767 .isCompatibleWith(Triple(Other.getTargetTripleString()));
768}
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)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
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
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:128
iterator end()
Definition StringMap.h:213
iterator find(StringRef Key)
Definition StringMap.h:226
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition StringMap.h:310
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:276
@ LastAMDGPUSubArch
Definition Triple.h:277
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 StringRef getCanonicalArchName(const Triple &T, StringRef Arch)
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 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 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 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.