1//===----------------------------------------------------------------------===//
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#include "clang/Basic/OffloadArch.h"
9
10#include "llvm/ADT/SmallVector.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/TargetParser/AMDGPUTargetParser.h"
13#include "llvm/TargetParser/NVPTXTargetParser.h"
14#include "llvm/TargetParser/Triple.h"
15
16namespace clang {
17
18OffloadArch OffloadArch::CudaDefault() {
19 return getNVPTX(K: llvm::NVPTX::parseArch(CPU: "sm_52"));
20}
21
22OffloadArch OffloadArch::HIPDefault() {
23 return getAMDGPU(K: llvm::AMDGPU::parseArchAMDGCN(CPU: "gfx906"));
24}
25
26const char *OffloadArchToString(OffloadArch A) {
27 switch (A.targetArch()) {
28 case OffloadArch::TargetArch::Unused:
29 return "";
30 case OffloadArch::TargetArch::Unknown:
31 return "unknown";
32 case OffloadArch::TargetArch::NVPTX:
33 return llvm::NVPTX::getArchName(Kind: A.nvptxKind()).data();
34 case OffloadArch::TargetArch::AMDGPU:
35 return llvm::AMDGPU::getArchNameAMDGCN(AK: A.amdgpuKind()).data();
36 case OffloadArch::TargetArch::AMDGCNSPIRV:
37 return "amdgcnspirv";
38 case OffloadArch::TargetArch::IntelCPU:
39 return "graniterapids";
40 case OffloadArch::TargetArch::IntelGPU:
41 return "bmg_g21";
42 case OffloadArch::TargetArch::Generic:
43 return "generic";
44 }
45 return "unknown";
46}
47
48const char *OffloadArchToVirtualArchString(OffloadArch A) {
49 switch (A.targetArch()) {
50 case OffloadArch::TargetArch::NVPTX:
51 return llvm::NVPTX::getVirtualArch(Kind: A.nvptxKind()).data();
52 case OffloadArch::TargetArch::AMDGPU:
53 case OffloadArch::TargetArch::AMDGCNSPIRV:
54 return "compute_amdgcn";
55 case OffloadArch::TargetArch::Unknown:
56 return "unknown";
57 case OffloadArch::TargetArch::Unused:
58 case OffloadArch::TargetArch::IntelCPU:
59 case OffloadArch::TargetArch::IntelGPU:
60 case OffloadArch::TargetArch::Generic:
61 return "";
62 }
63 return "unknown";
64}
65
66OffloadArch StringToOffloadArch(llvm::StringRef S) {
67 // The empty string denotes the "unused" architecture.
68 if (S.empty())
69 return OffloadArch::getUnused();
70
71 // Non-GPU-table pseudo/sentinel architectures.
72 if (S == "amdgcnspirv")
73 return OffloadArch::getAMDGCNSPIRV();
74 if (S == "generic")
75 return OffloadArch::getGeneric();
76 if (S == "graniterapids")
77 return OffloadArch::getIntel(V: OffloadArch::TargetArch::IntelCPU,
78 A: OffloadArch::IntelArch::GRANITERAPIDS);
79 if (S == "bmg_g21")
80 return OffloadArch::getIntel(V: OffloadArch::TargetArch::IntelGPU,
81 A: OffloadArch::IntelArch::BMG_G21);
82
83 // Otherwise defer to the vendor TargetParser GPU lists.
84 if (llvm::NVPTX::GPUKind NV = llvm::NVPTX::parseArch(CPU: S))
85 return OffloadArch::getNVPTX(K: NV);
86 if (llvm::AMDGPU::GPUKind AK = llvm::AMDGPU::parseArchAMDGCN(CPU: S))
87 return OffloadArch::getAMDGPU(K: AK);
88 return OffloadArch::getUnknown();
89}
90
91void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) {
92#define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \
93 Values.push_back(NAME);
94#include "llvm/TargetParser/NVPTXTargetParser.def"
95 llvm::AMDGPU::fillValidArchListAMDGCN(Values, SubArch: llvm::Triple::NoSubArch);
96}
97
98OffloadArch getSubArchOffloadArch(llvm::Triple::SubArchType SubArch) {
99 llvm::AMDGPU::GPUKind AK = llvm::AMDGPU::getGPUKindFromSubArch(SubArch);
100 if (AK == llvm::AMDGPU::GK_NONE)
101 return OffloadArch::getUnknown();
102 return OffloadArch::getAMDGPU(K: AK);
103}
104
105llvm::Triple::SubArchType getOffloadArchSubArch(OffloadArch ID) {
106 if (!ID.isAMDGPU())
107 return llvm::Triple::NoSubArch;
108 return llvm::AMDGPU::getSubArch(AK: ID.amdgpuKind());
109}
110
111llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
112 OffloadArch ID) {
113 if (ID.isAMDGCNSPIRV())
114 return llvm::Triple(llvm::Triple::spirv64, llvm::Triple::NoSubArch,
115 llvm::Triple::AMD, llvm::Triple::AMDHSA);
116
117 if (ID.isNVPTX()) {
118 llvm::Triple::ArchType Arch = DefaultToolchainTriple.isArch64Bit()
119 ? llvm::Triple::nvptx64
120 : llvm::Triple::nvptx;
121 return llvm::Triple(Arch, llvm::Triple::NoSubArch, llvm::Triple::NVIDIA,
122 llvm::Triple::CUDA);
123 }
124
125 if (ID.isAMDGPU())
126 return llvm::Triple(llvm::Triple::amdgpu, llvm::Triple::NoSubArch,
127 llvm::Triple::AMD, llvm::Triple::AMDHSA);
128
129 return {};
130}
131
132} // namespace clang
133