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 AMDGPUFeatureBitset Features;
40 IsaVersion Version;
41 StringTable::Offset FamilyName;
42 uint8_t MaxWavesPerEU;
43 uint32_t MaxHWAddressableLocalMemorySize;
44 uint8_t LDSBankCount;
45 uint8_t BufferResourceNumRecordsWidth;
46};
47
48// Per-GPU data for the R600 GPUKinds.
49struct R600Info {
50 StringTable::Offset Name;
51 R600FeatureBitset Features;
52};
53
54#define GET_AMDGPU_NAME_TABLE
55#define GET_AMDGPU_GPU_TABLE
56#define GET_AMDGPU_GPU_ALIAS_TABLE
57#define GET_AMDGPU_MAJOR_SUBARCH
58#define GET_AMDGPU_SUBARCH_NAME
59#define GET_AMDGPU_FEATURE_NAME_TABLE
60#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"
61
62#define GET_R600_NAME_TABLE
63#define GET_R600_GPU_TABLE
64#define GET_R600_GPU_ALIAS_TABLE
65#define GET_R600_FEATURE_NAME_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
180 if (SubArch < Triple::FirstAMDGPUSubArch ||
182 return GK_NONE;
183 return AMDGPUSubArchToGPUKind[SubArch - Triple::FirstAMDGPUSubArch];
184}
185
191
193 if (A == B || A == Triple::NoSubArch || B == Triple::NoSubArch)
194 return true;
195
198
199 // One side is the major-family subarch covering the other's family.
200 if (A == MajorA)
201 return MajorA == MajorB;
202 if (B == MajorB)
203 return MajorA == MajorB;
204
205 return false;
206}
207
209 // An unrecognized GPU is never valid.
210 if (AK == GK_NONE)
211 return false;
212 // A legacy triple without a subarch accepts any known GPU.
213 if (SubArch == Triple::NoSubArch)
214 return true;
215
216 // Reject the dummy "generic" targets
217 Triple::SubArchType GPUSubArch = getSubArch(AK);
218 if (GPUSubArch == Triple::NoSubArch)
219 return false;
220
221 return isSubArchCompatible(GPUSubArch, SubArch);
222}
223
227
229 const GPUInfo *Info = getAMDGPUInfo(AK);
230 return Info && Info->SubArch == Triple::NoSubArch;
231}
232
236
238 // Tolerate subarch mismatch if one entry is none. This is a hack for bitcode
239 // libraries.
240 // There's a missing enum entry for an unknown subarch. Make sure the
241 // subarch is really empty.
242 if (A.getSubArch() == Triple::NoSubArch)
243 return A.getArchName().size() == 6;
244
245 if (B.getSubArch() == Triple::NoSubArch)
246 return B.getArchName().size() == 6;
247
248 return isSubArchCompatible(A.getSubArch(), B.getSubArch());
249}
250
251std::string AMDGPU::mergeSubArch(const Triple &A, const Triple &B) {
252 if (A.getSubArch() == Triple::NoSubArch)
253 return B.str();
254 if (B.getSubArch() == Triple::NoSubArch)
255 return A.str();
256
257 Triple::SubArchType MajorA = AMDGPU::getMajorSubArch(A.getSubArch());
258 Triple::SubArchType MajorB = AMDGPU::getMajorSubArch(B.getSubArch());
259
260 // With a compatible major arch, return the specific subarch.
261 if (A.getSubArch() == MajorA) {
262 if (MajorA == MajorB)
263 return B.str();
264 }
265
266 if (B.getSubArch() == MajorB) {
267 if (MajorA == MajorB)
268 return A.str();
269 }
270
271 // Invalid case.
272 return B.str();
273}
274
276 const GPUInfo *Info = getAMDGPUInfo(AK);
277 return Info ? AMDGPUNameStrTab[Info->Name] : "";
278}
279
281 if (SubArch < Triple::FirstAMDGPUSubArch ||
283 return "";
284 return AMDGPUNameStrTab[AMDGPUSubArchNameOffsets[SubArch -
286}
287
289 if (SubArch == Triple::NoSubArch)
290 return AMDGPUNameStrTab[AMDGPUNoSubArchNameOffset];
291
293 SubArch <= Triple::LastAMDGPUSubArch &&
294 "expected an AMDGPU subarch or NoSubArch");
295 return AMDGPUNameStrTab
296 [AMDGPUSubArchTripleNameOffsets[SubArch - Triple::FirstAMDGPUSubArch]];
297}
298
300 const R600Info *Info = getR600Info(AK);
301 return Info ? R600NameStrTab[Info->Name] : "";
302}
303
305 return parseArchImpl(CPU, AMDGPUGPUTable, AMDGPUFirstGPUKind,
306 AMDGPUNameStrTab, AMDGPUGPUAliases);
307}
308
310 return parseArchImpl(CPU, R600GPUTable, R600FirstGPUKind, R600NameStrTab,
311 R600GPUAliases);
312}
313
315 static constexpr AMDGPUFeatureBitset Empty{};
316 const GPUInfo *Info = getAMDGPUInfo(AK);
317 return Info ? Info->Features : Empty;
318}
319
321 static constexpr R600FeatureBitset Empty{};
322 const R600Info *Info = getR600Info(AK);
323 return Info ? Info->Features : Empty;
324}
325
328 for (unsigned I = 0; I != NUM_FEATURES; ++I) {
329 if (Features.test(I))
330 Names.push_back(AMDGPUNameStrTab[AMDGPUFeatureNames[I]]);
331 }
332}
333
335 Triple::SubArchType SubArch) {
336 // XXX: Should this only report unique canonical names?
337 // An alias shares its GPU's GPUKind, so it is filtered alongside it.
338 for (unsigned I = 0; I != std::size(AMDGPUGPUTable); ++I) {
339 GPUKind Kind = static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
340 if (AMDGPUGPUTable[I].SubArch != Triple::NoSubArch &&
341 isCPUValidForSubArch(SubArch, Kind))
342 Values.push_back(AMDGPUNameStrTab[AMDGPUGPUTable[I].Name]);
343 }
344
345 for (const GPUNameAlias &A : AMDGPUGPUAliases) {
346 if (isCPUValidForSubArch(SubArch, A.Kind))
347 Values.push_back(AMDGPUNameStrTab[A.AltName]);
348 }
349}
350
352 for (const R600Info &Info : R600GPUTable)
353 Values.push_back(R600NameStrTab[Info.Name]);
354 for (const GPUNameAlias &A : R600GPUAliases)
355 Values.push_back(R600NameStrTab[A.AltName]);
356}
357
359 const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(GPU));
360 return Info ? Info->Version : IsaVersion{0, 0, 0};
361}
362
364 const GPUInfo *Info = getAMDGPUInfo(getGPUKindFromSubArch(SubArch));
365 return Info ? Info->Version : IsaVersion{0, 0, 0};
366}
367
370 if (Version.Major >= 8)
371 return 800;
372 return 512;
373}
374
377 if (Version.Major >= 8)
378 return 800;
379 return 512;
380}
381
383 if (getFeatureBitset(AK).test(FEAT_SGPR_INIT_BUG))
385
387 if (Version.Major >= 10)
388 return 106;
389 if (Version.Major >= 8)
390 return 102;
391 return 104;
392}
393
395 if (getFeatureBitset(getGPUKindFromSubArch(SubArch)).test(FEAT_SGPR_INIT_BUG))
397
399 if (Version.Major >= 10)
400 return 106;
401 if (Version.Major >= 8)
402 return 102;
403 return 104;
404}
405
408 if (Version.Major >= 10)
409 return getAddressableNumSGPRs(AK);
410 if (Version.Major >= 8)
411 return 16;
412 return 8;
413}
414
417 if (Version.Major >= 10)
418 return getAddressableNumSGPRs(SubArch);
419 if (Version.Major >= 8)
420 return 16;
421 return 8;
422}
423
424unsigned AMDGPU::getVGPRAllocGranule(GPUKind AK, bool IsWave32) {
425 const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
426 if (Features.test(FEAT_GFX90A_INSTS))
427 return 8;
428 if (Features.test(FEAT_1536_PHYSICAL_VGPRS))
429 return IsWave32 ? 24 : 12;
430 if (Features.test(FEAT_GFX10_3_INSTS))
431 return IsWave32 ? 16 : 8;
432 return IsWave32 ? 8 : 4;
433}
434
436 bool IsWave32) {
437 return getVGPRAllocGranule(getGPUKindFromSubArch(SubArch), IsWave32);
438}
439
440unsigned AMDGPU::getTotalNumVGPRs(GPUKind AK, bool IsWave32) {
441 const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
442 if (Features.test(FEAT_GFX90A_INSTS))
443 return 512;
444 if (!Features.test(FEAT_GFX10_INSTS))
445 return 256;
446 if (Features.test(FEAT_1536_PHYSICAL_VGPRS))
447 return IsWave32 ? 1536 : 768;
448 return IsWave32 ? 1024 : 512;
449}
450
451unsigned AMDGPU::getTotalNumVGPRs(Triple::SubArchType SubArch, bool IsWave32) {
452 return getTotalNumVGPRs(getGPUKindFromSubArch(SubArch), IsWave32);
453}
454
455unsigned AMDGPU::getAddressableNumVGPRs(GPUKind AK, bool IsWave32) {
456 const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
457 // The unified register file makes the AGPRs addressable as VGPRs.
458 if (Features.test(FEAT_GFX90A_INSTS))
459 return 512;
460 if (Features.test(FEAT_1024_ADDRESSABLE_VGPRS))
461 return IsWave32 ? 1024 : 512;
462 return 256;
463}
464
466 bool IsWave32) {
467 return getAddressableNumVGPRs(getGPUKindFromSubArch(SubArch), IsWave32);
468}
469
471 const GPUInfo *Info = getAMDGPUInfo(AK);
472 return Info ? Info->MaxHWAddressableLocalMemorySize : 32768;
473}
474
475unsigned
479
481 const GPUInfo *Info = getAMDGPUInfo(AK);
482 return Info ? Info->LDSBankCount : 32;
483}
484
488
490 const GPUInfo *Info = getAMDGPUInfo(AK);
491 if (!Info || Info->BufferResourceNumRecordsWidth == 0)
492 return std::nullopt;
493 return Info->BufferResourceNumRecordsWidth;
494}
495
496std::optional<unsigned>
500
502 const GPUInfo *Info = getAMDGPUInfo(AK);
503 return Info ? Info->MaxWavesPerEU : 10;
504}
505
509
511 assert(T.isAMDGPU());
512 auto ProcKind = T.isAMDGCN() ? parseArchAMDGCN(Arch) : parseArchR600(Arch);
513 if (ProcKind == GK_NONE)
514 return StringRef();
515
516 return T.isAMDGCN() ? getArchNameAMDGCN(ProcKind) : getArchNameR600(ProcKind);
517}
518
519// Capability features clang queries via the feature bitset but must not
520// serialize into the target-feature string.
521//
522// FIXME: This is hacky, we shouldn't have mismatches between the bitset and
523// feature string map.
525 FEAT_FAST_FMAF,
526 FEAT_FAST_DENORMAL_F32,
527 FEAT_SUPPORTS_WAVE32,
528 FEAT_SUPPORTS_WGP,
529 FEAT_XNACK_SUPPORT,
530 FEAT_SRAMECC_SUPPORT,
531 FEAT_XNACK_ON_OFF_MODES,
532 FEAT_APERTURE_REGS,
533 FEAT_GET_DOORBELL_ID,
534 FEAT_AGPR_ALLOC,
535 FEAT_1536_PHYSICAL_VGPRS,
536 FEAT_HALF_ADDRESSABLE_PHYSICAL_LOCAL_MEMORY,
537 FEAT_1024_ADDRESSABLE_VGPRS};
538
539// Add a GPU's features (minus the frontend-only ones) to \p Features. With \p
540// Overwrite false, existing entries are kept so user -mattr overrides win.
541static void addGPUFeatures(const GPUInfo &Info, bool Overwrite,
542 StringMap<bool> &Features) {
544 getFeatureNames(Info.Features & ~FrontendOnlyFeatures, Names);
545 for (StringRef Name : Names) {
546 if (Overwrite)
547 Features[Name] = true;
548 else
549 Features.insert({Name, true});
550 }
551}
552
553/// Add a GPU's default features to \p Features (preserving user overrides) and
554/// validate any requested wavesize.
555static std::pair<FeatureError, StringRef>
557 StringMap<bool> &Features) {
558 // With no explicit GPU, the triple's subarch identifies the target.
559 GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch
560 ? getGPUKindFromSubArch(T.getSubArch())
561 : parseArchAMDGCN(GPU);
562 const GPUInfo *Info = getAMDGPUInfo(Kind);
563
564 // A bare subarch triple (no -target-cpu) still pins down the target, so it is
565 // not a null GPU. The target's native wavesize (if single-mode) is in the
566 // feature bitset; a dual-mode GPU has neither wave bit set.
567 const bool IsNullGPU = T.getSubArch() == Triple::NoSubArch && GPU.empty();
568 const bool TargetHasWave32 =
569 Info && Info->Features.test(FEAT_WAVEFRONTSIZE32);
570 const bool TargetHasWave64 =
571 Info && Info->Features.test(FEAT_WAVEFRONTSIZE64);
572
573 auto Wave32Itr = Features.find("wavefrontsize32");
574 auto Wave64Itr = Features.find("wavefrontsize64");
575 const bool EnableWave32 =
576 Wave32Itr != Features.end() && Wave32Itr->getValue();
577 const bool EnableWave64 =
578 Wave64Itr != Features.end() && Wave64Itr->getValue();
579 const bool DisableWave32 =
580 Wave32Itr != Features.end() && !Wave32Itr->getValue();
581 const bool DisableWave64 =
582 Wave64Itr != Features.end() && !Wave64Itr->getValue();
583
584 if (EnableWave32 && EnableWave64)
586 "'+wavefrontsize32' and '+wavefrontsize64' are mutually exclusive"};
587 if (DisableWave32 && DisableWave64)
589 "'-wavefrontsize32' and '-wavefrontsize64' are mutually exclusive"};
590
591 if (!IsNullGPU) {
592 if (TargetHasWave64) {
593 if (EnableWave32)
594 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize32"};
595 if (DisableWave64)
596 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize64"};
597 }
598
599 if (TargetHasWave32) {
600 if (EnableWave64)
601 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize64"};
602 if (DisableWave32)
603 return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize32"};
604 }
605 }
606
607 // Don't assume any wavesize with an unknown subtarget.
608 // Default to wave32 if target supports both.
609 if (!IsNullGPU && !EnableWave32 && !EnableWave64 && !TargetHasWave32 &&
610 !TargetHasWave64)
611 Features.insert({"wavefrontsize32", true});
612
613 // Merge the target defaults, keeping any user -mattr overrides.
614 if (Info)
615 addGPUFeatures(*Info, /*Overwrite=*/false, Features);
616
617 return {NO_ERROR, StringRef()};
618}
619
620/// Fills Features map with default values for given target GPU.
621/// \p Features contains overriding target features and this function returns
622/// default target features with entries overridden by \p Features.
623std::pair<FeatureError, StringRef>
625 StringMap<bool> &Features) {
626 // XXX - What does the member GPU mean if device name string passed here?
627 if (T.isSPIRV() && T.getOS() == Triple::OSType::AMDHSA) {
628 // AMDGCN SPIRV must support the union of all AMDGCN features.
631 for (StringRef G : GPUs)
632 if (const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(G)))
633 addGPUFeatures(*Info, /*Overwrite=*/true, Features);
634 Features["wavefrontsize32"] = true;
635 Features["wavefrontsize64"] = true;
636 } else if (T.isAMDGCN()) {
637 return fillAMDGCNFeatureMap(GPU, T, Features);
638 } else {
639 if (GPU.empty())
640 GPU = "r600";
641
642 switch (llvm::AMDGPU::parseArchR600(GPU)) {
643 case GK_CAYMAN:
644 case GK_CYPRESS:
645 case GK_RV770:
646 case GK_RV670:
647 // TODO: Add fp64 when implemented.
648 break;
649 case GK_TURKS:
650 case GK_CAICOS:
651 case GK_BARTS:
652 case GK_SUMO:
653 case GK_REDWOOD:
654 case GK_JUNIPER:
655 case GK_CEDAR:
656 case GK_RV730:
657 case GK_RV710:
658 case GK_RS880:
659 case GK_R630:
660 case GK_R600:
661 break;
662 default:
663 llvm_unreachable("Unhandled GPU!");
664 }
665 }
666 return {NO_ERROR, StringRef()};
667}
668
669TargetID::TargetID(GPUKind Arch, const Triple &TT, TargetIDSetting XnackSetting,
670 TargetIDSetting SramEccSetting)
671 : Arch(Arch),
672 TargetTripleString(TT.normalize(Triple::CanonicalForm::FOUR_IDENT)),
673 XnackSetting(XnackSetting), SramEccSetting(SramEccSetting),
674 IsAMDHSA(TT.getOS() == Triple::AMDHSA) {}
675
676// Parse a feature modifier sign ("+"/"-"). Returns "Unsupported" if \p Sign is
677// neither (i.e. the modifier is malformed).
679 if (Sign == "+")
680 return TargetIDSetting::On;
681 if (Sign == "-")
682 return TargetIDSetting::Off;
683
684 return TargetIDSetting::Unsupported;
685}
686
687// Derive the architecture from the processor name in \p TargetIDStr. "generic"
688// and the empty processor name act as a wildcard.
689static GPUKind getGPUKindFromTargetID(const Triple &TT, StringRef TargetIDStr) {
690 StringRef CPUName = TargetIDStr.split(':').first;
691 return (CPUName.empty() || CPUName == "generic")
692 ? getGPUKindFromSubArch(TT.getSubArch())
693 : parseArchAMDGCN(CPUName);
694}
695
696// Compute the default xnack/sramecc settings for processor \p Arch, before any
697// explicit feature modifiers are applied.
701 const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
702 // xnack with on/off modes defaults to Any; supported without on/off modes is
703 // hardwired On (e.g. gfx1250); unsupported is Unsupported.
704 if (!Features.test(FEAT_XNACK_SUPPORT))
705 XnackSetting = TargetIDSetting::Unsupported;
706 else if (Features.test(FEAT_XNACK_ON_OFF_MODES))
707 XnackSetting = TargetIDSetting::Any;
708 else
709 XnackSetting = TargetIDSetting::On;
710 SramEccSetting = Features.test(FEAT_SRAMECC_SUPPORT)
711 ? TargetIDSetting::Any
712 : TargetIDSetting::Unsupported;
713}
714
715// Compute the xnack/sramecc settings for processor \p Arch from the
716// processor+features string \p TargetIDStr
717// (e.g. "gfx90a:xnack+:sramecc-"). Returns false if a modifier names an unknown
718// or repeated feature, names one the processor does not support, or has a
719// malformed sign.
720static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
723 const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
725
726 // The first component is the processor; the rest are feature modifiers of the
727 // form "<feature><+|->".
729 TargetIDStr.split(Split, ':');
730 bool SeenXnack = false;
731 bool SeenSramEcc = false;
732 bool Valid = true;
733 for (unsigned I = 1, E = Split.size(); I != E; ++I) {
734 StringRef FeatureString = Split[I];
735 if (FeatureString.consume_front("xnack")) {
737 // An xnack modifier is only valid with on/off modes: rejected when xnack
738 // is unsupported or hardwired on (e.g. gfx1250).
739 if (SeenXnack || !Features.test(FEAT_XNACK_ON_OFF_MODES) ||
740 Sign == TargetIDSetting::Unsupported)
741 Valid = false;
742 else
743 XnackSetting = Sign;
744 SeenXnack = true;
745 } else if (FeatureString.consume_front("sramecc")) {
747 if (SeenSramEcc || SramEccSetting == TargetIDSetting::Unsupported ||
748 Sign == TargetIDSetting::Unsupported)
749 Valid = false;
750 else
751 SramEccSetting = Sign;
752 SeenSramEcc = true;
753 } else {
754 // Unknown feature name.
755 Valid = false;
756 }
757 }
758 return Valid;
759}
760
761TargetID::TargetID(const Triple &TT, StringRef TargetIDStr)
762 : TargetID(getGPUKindFromTargetID(TT, TargetIDStr), TT,
764 // Derive the feature settings from the string. Validity is not checked here;
765 // parseTargetIDString validates untrusted input.
766 computeTargetIDFeatures(Arch, TargetIDStr, XnackSetting, SramEccSetting);
767}
768
770 StringRef FeatureString) {
771 GPUKind Arch = parseArchAMDGCN(CPU);
772 TargetIDSetting XnackSetting, SramEccSetting;
773 getDefaultTargetIDFeatures(Arch, XnackSetting, SramEccSetting);
774
775 // Apply the +/-xnack and +/-sramecc modifiers from the feature string, only
776 // for targets that can toggle the corresponding mode.
777 bool XnackToggleable = XnackSetting == TargetIDSetting::Any;
778 bool SramEccToggleable = SramEccSetting == TargetIDSetting::Any;
780 FeatureString.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
781 for (StringRef Feature : Features) {
782 TargetIDSetting Sign =
783 getTargetIDSettingFromFeatureString(Feature.take_front());
784 if (Sign == TargetIDSetting::Unsupported)
785 continue;
786 StringRef Name = Feature.drop_front();
787 if (Name == "xnack" && XnackToggleable)
788 XnackSetting = Sign;
789 else if (Name == "sramecc" && SramEccToggleable)
790 SramEccSetting = Sign;
791 }
792
793 return TargetID(Arch, TT, XnackSetting, SramEccSetting);
794}
795
796std::optional<TargetID> TargetID::parse(const Triple &TT,
797 StringRef ProcAndFeatures) {
798 if (!TT.isAMDGCN())
799 return std::nullopt;
800
801 // Filter out unrecognized subarch suffixes.
802 if (TT.getSubArch() == Triple::NoSubArch && TT.getArchName() != "amdgcn")
803 return std::nullopt;
804
805 // A named processor (i.e. not the empty/generic wildcard, which is resolved
806 // from the triple's subarch) must be a recognized GPU that is consistent with
807 // the triple's subarch.
808 StringRef CPUName = ProcAndFeatures.split(':').first;
809 if (!CPUName.empty() && CPUName != "generic" &&
810 !isCPUValidForSubArch(TT.getSubArch(), CPUName))
811 return std::nullopt;
812
813 // Parse the processor and its feature modifiers, then construct directly from
814 // the resulting fields.
815 GPUKind Arch = getGPUKindFromTargetID(TT, ProcAndFeatures);
816 TargetIDSetting XnackSetting, SramEccSetting;
817 if (!computeTargetIDFeatures(Arch, ProcAndFeatures, XnackSetting,
818 SramEccSetting))
819 return std::nullopt;
820
821 return TargetID(Arch, TT, XnackSetting, SramEccSetting);
822}
823
824std::optional<TargetID>
826 // Split on '-' to get arch-vendor-os-environment-processor:features. There is
827 // a single dash separator after the 4-component triple, so the
828 // processor+features field must be present (even if empty).
830 TargetIDDirective.split(Parts, '-', /*MaxSplit=*/4);
831 if (Parts.size() < 5)
832 return std::nullopt;
833
834 return parse(Triple(Parts[0], Parts[1], Parts[2], Parts[3]), Parts[4]);
835}
836
837// Returns true if \p Arch hardwires xnack on (supports xnack but has no on/off
838// modes, e.g. gfx1250), so xnack is not a selectable target-id modifier.
839static bool isXnackHardwiredOn(GPUKind Arch) {
840 const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
841 return Features.test(FEAT_XNACK_SUPPORT) &&
842 !Features.test(FEAT_XNACK_ON_OFF_MODES);
843}
844
845// Append the explicit (On/Off) sramecc/xnack feature modifiers in canonical
846// order, e.g. ":sramecc-:xnack+". Xnack is never emitted for hardwired-on
847// targets.
849 TargetIDSetting Xnack,
850 bool XnackHardwiredOn) {
851 if (SramEcc == TargetIDSetting::Off)
852 OS << ":sramecc-";
853 else if (SramEcc == TargetIDSetting::On)
854 OS << ":sramecc+";
855
856 if (XnackHardwiredOn)
857 return;
858
859 if (Xnack == TargetIDSetting::Off)
860 OS << ":xnack-";
861 else if (Xnack == TargetIDSetting::On)
862 OS << ":xnack+";
863}
864
865void TargetID::print(raw_ostream &StreamRep) const {
866 StreamRep << TargetTripleString << '-' << getArchNameAMDGCN(Arch);
867
868 if (IsAMDHSA) {
870 isXnackHardwiredOn(Arch));
871 }
872}
873
874std::string TargetID::toString() const {
875 std::string Str;
876 raw_string_ostream OS(Str);
877 OS << *this;
878 return Str;
879}
880
886
888 std::string Str;
889 raw_string_ostream OS(Str);
891 return Str;
892}
893
895 return Arch == Other.Arch && XnackSetting == Other.XnackSetting &&
896 SramEccSetting == Other.SramEccSetting && IsAMDHSA == Other.IsAMDHSA &&
897 TargetTripleString == Other.TargetTripleString;
898}
899
901 TargetIDSetting Requested) {
902 return Provided == TargetIDSetting::Any ||
903 Provided == TargetIDSetting::Unsupported || Provided == Requested;
904}
905
907 // The processor and feature settings must match exactly
908 if (Arch != Other.Arch || XnackSetting != Other.XnackSetting ||
909 SramEccSetting != Other.SramEccSetting)
910 return false;
911
913 .isCompatibleWith(Triple(Other.getTargetTripleString()));
914}
915
917 // A major-family/generic processor (e.g. amdgpu9) provides for a specific
918 // member of its family (e.g. gfx900), but not the reverse. Otherwise the
919 // processors must match.
920 if (Arch != Other.Arch && Arch != GK_NONE && Other.Arch != GK_NONE) {
921 Triple::SubArchType ThisSubArch = getSubArch(Arch);
922 if (ThisSubArch != getMajorSubArch(ThisSubArch) ||
923 ThisSubArch != getMajorSubArch(getSubArch(Other.Arch)))
924 return false;
925 }
926
927 if (!featureProvidesFor(XnackSetting, Other.XnackSetting) ||
928 !featureProvidesFor(SramEccSetting, Other.SramEccSetting))
929 return false;
930
932 .isCompatibleWith(Triple(Other.getTargetTripleString()));
933}
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 void getDefaultTargetIDFeatures(GPUKind Arch, TargetIDSetting &XnackSetting, TargetIDSetting &SramEccSetting)
static TargetIDSetting getTargetIDSettingFromFeatureString(StringRef Sign)
static bool featureProvidesFor(TargetIDSetting Provided, TargetIDSetting Requested)
static bool isXnackHardwiredOn(GPUKind Arch)
static void addGPUFeatures(const GPUInfo &Info, bool Overwrite, StringMap< bool > &Features)
static const AMDGPUFeatureBitset FrontendOnlyFeatures
static void printFeatureModifiers(raw_ostream &OS, TargetIDSetting SramEcc, TargetIDSetting Xnack, bool XnackHardwiredOn)
#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
static TargetID createFromSubtargetFeatures(const Triple &TT, StringRef CPU, StringRef FeatureString)
Construct a TargetID for triple TT and processor CPU, taking the xnack/sramecc modes from the subtarg...
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:278
@ LastAMDGPUSubArch
Definition Triple.h:279
LLVM_ABI bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition Triple.cpp:2274
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 void fillValidArchListR600(SmallVectorImpl< StringRef > &Values)
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 getTotalNumVGPRs(GPUKind AK, bool IsWave32)
LLVM_ABI unsigned getTotalNumSGPRs(GPUKind AK)
LLVM_ABI std::optional< unsigned > getBufferResourceNumRecordsWidth(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 unsigned getAddressableNumVGPRs(GPUKind AK, bool IsWave32)
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 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 const R600FeatureBitset & getFeatureBitsetR600(GPUKind AK)
Returns R600 GPU AK's feature bitset, or an empty bitset if unknown.
Bitset< R600_NUM_FEATURES > R600FeatureBitset
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.