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