1#include "clang/Basic/Cuda.h"
2
3#include "llvm/ADT/Twine.h"
4#include "llvm/Support/ErrorHandling.h"
5#include "llvm/Support/VersionTuple.h"
6
7namespace clang {
8
9struct CudaVersionMapEntry {
10 const char *Name;
11 CudaVersion Version;
12 llvm::VersionTuple TVersion;
13};
14#define CUDA_ENTRY(major, minor) \
15 { \
16 #major "." #minor, CudaVersion::CUDA_##major##minor, \
17 llvm::VersionTuple(major, minor) \
18 }
19
20static const CudaVersionMapEntry CudaNameVersionMap[] = {
21 CUDA_ENTRY(7, 0),
22 CUDA_ENTRY(7, 5),
23 CUDA_ENTRY(8, 0),
24 CUDA_ENTRY(9, 0),
25 CUDA_ENTRY(9, 1),
26 CUDA_ENTRY(9, 2),
27 CUDA_ENTRY(10, 0),
28 CUDA_ENTRY(10, 1),
29 CUDA_ENTRY(10, 2),
30 CUDA_ENTRY(11, 0),
31 CUDA_ENTRY(11, 1),
32 CUDA_ENTRY(11, 2),
33 CUDA_ENTRY(11, 3),
34 CUDA_ENTRY(11, 4),
35 CUDA_ENTRY(11, 5),
36 CUDA_ENTRY(11, 6),
37 CUDA_ENTRY(11, 7),
38 CUDA_ENTRY(11, 8),
39 CUDA_ENTRY(12, 0),
40 CUDA_ENTRY(12, 1),
41 CUDA_ENTRY(12, 2),
42 CUDA_ENTRY(12, 3),
43 CUDA_ENTRY(12, 4),
44 CUDA_ENTRY(12, 5),
45 CUDA_ENTRY(12, 6),
46 CUDA_ENTRY(12, 8),
47 CUDA_ENTRY(12, 9),
48 CUDA_ENTRY(13, 0),
49 {.Name: "", .Version: CudaVersion::NEW, .TVersion: llvm::VersionTuple(std::numeric_limits<int>::max())},
50 {.Name: "unknown", .Version: CudaVersion::UNKNOWN, .TVersion: {}} // End of list tombstone.
51};
52#undef CUDA_ENTRY
53
54const char *CudaVersionToString(CudaVersion V) {
55 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
56 if (I->Version == V)
57 return I->Name;
58
59 return CudaVersionToString(V: CudaVersion::UNKNOWN);
60}
61
62CudaVersion CudaStringToVersion(const llvm::Twine &S) {
63 std::string VS = S.str();
64 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
65 if (I->Name == VS)
66 return I->Version;
67 return CudaVersion::UNKNOWN;
68}
69
70CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
71 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
72 if (I->TVersion == Version)
73 return I->Version;
74 return CudaVersion::UNKNOWN;
75}
76
77CudaVersion MinVersionForOffloadArch(OffloadArch A) {
78 if (A == OffloadArch::UNKNOWN)
79 return CudaVersion::UNKNOWN;
80
81 // AMD GPUs do not depend on CUDA versions.
82 if (IsAMDOffloadArch(A))
83 return CudaVersion::CUDA_70;
84
85 switch (A) {
86 case OffloadArch::SM_20:
87 case OffloadArch::SM_21:
88 case OffloadArch::SM_30:
89 case OffloadArch::SM_32_:
90 case OffloadArch::SM_35:
91 case OffloadArch::SM_37:
92 case OffloadArch::SM_50:
93 case OffloadArch::SM_52:
94 case OffloadArch::SM_53:
95 return CudaVersion::CUDA_70;
96 case OffloadArch::SM_60:
97 case OffloadArch::SM_61:
98 case OffloadArch::SM_62:
99 return CudaVersion::CUDA_80;
100 case OffloadArch::SM_70:
101 return CudaVersion::CUDA_90;
102 case OffloadArch::SM_72:
103 return CudaVersion::CUDA_91;
104 case OffloadArch::SM_75:
105 return CudaVersion::CUDA_100;
106 case OffloadArch::SM_80:
107 return CudaVersion::CUDA_110;
108 case OffloadArch::SM_86:
109 return CudaVersion::CUDA_111;
110 case OffloadArch::SM_87:
111 return CudaVersion::CUDA_114;
112 case OffloadArch::SM_89:
113 case OffloadArch::SM_90:
114 return CudaVersion::CUDA_118;
115 case OffloadArch::SM_90a:
116 return CudaVersion::CUDA_120;
117 case OffloadArch::SM_100:
118 case OffloadArch::SM_100a:
119 case OffloadArch::SM_101:
120 case OffloadArch::SM_101a:
121 case OffloadArch::SM_120:
122 case OffloadArch::SM_120a:
123 return CudaVersion::CUDA_128;
124 case OffloadArch::SM_103:
125 case OffloadArch::SM_103a:
126 case OffloadArch::SM_121:
127 case OffloadArch::SM_121a:
128 return CudaVersion::CUDA_129;
129 case OffloadArch::SM_88:
130 case OffloadArch::SM_110:
131 case OffloadArch::SM_110a:
132 return CudaVersion::CUDA_130;
133 default:
134 llvm_unreachable("invalid enum");
135 }
136}
137
138CudaVersion MaxVersionForOffloadArch(OffloadArch A) {
139 // AMD GPUs do not depend on CUDA versions.
140 if (IsAMDOffloadArch(A))
141 return CudaVersion::NEW;
142
143 switch (A) {
144 case OffloadArch::UNKNOWN:
145 return CudaVersion::UNKNOWN;
146 case OffloadArch::SM_20:
147 case OffloadArch::SM_21:
148 return CudaVersion::CUDA_80;
149 case OffloadArch::SM_30:
150 case OffloadArch::SM_32_:
151 return CudaVersion::CUDA_102;
152 case OffloadArch::SM_35:
153 case OffloadArch::SM_37:
154 return CudaVersion::CUDA_118;
155 case OffloadArch::SM_101:
156 case OffloadArch::SM_101a:
157 return CudaVersion::CUDA_129;
158 default:
159 return CudaVersion::NEW;
160 }
161}
162
163bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
164 return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
165}
166
167bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
168 switch (Feature) {
169 case CudaFeature::CUDA_USES_NEW_LAUNCH:
170 return Version >= CudaVersion::CUDA_92;
171 case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
172 return Version >= CudaVersion::CUDA_101;
173 }
174 llvm_unreachable("Unknown CUDA feature.");
175}
176
177unsigned CudaArchToID(OffloadArch Arch) {
178 switch (Arch) {
179 case OffloadArch::SM_20:
180 return 200;
181 case OffloadArch::SM_21:
182 return 210;
183 case OffloadArch::SM_30:
184 return 300;
185 case OffloadArch::SM_32_:
186 return 320;
187 case OffloadArch::SM_35:
188 return 350;
189 case OffloadArch::SM_37:
190 return 370;
191 case OffloadArch::SM_50:
192 return 500;
193 case OffloadArch::SM_52:
194 return 520;
195 case OffloadArch::SM_53:
196 return 530;
197 case OffloadArch::SM_60:
198 return 600;
199 case OffloadArch::SM_61:
200 return 610;
201 case OffloadArch::SM_62:
202 return 620;
203 case OffloadArch::SM_70:
204 return 700;
205 case OffloadArch::SM_72:
206 return 720;
207 case OffloadArch::SM_75:
208 return 750;
209 case OffloadArch::SM_80:
210 return 800;
211 case OffloadArch::SM_86:
212 return 860;
213 case OffloadArch::SM_87:
214 return 870;
215 case OffloadArch::SM_88:
216 return 880;
217 case OffloadArch::SM_89:
218 return 890;
219 case OffloadArch::SM_90:
220 case OffloadArch::SM_90a:
221 return 900;
222 case OffloadArch::SM_100:
223 case OffloadArch::SM_100a:
224 return 1000;
225 case OffloadArch::SM_101:
226 case OffloadArch::SM_101a:
227 return 1010;
228 case OffloadArch::SM_103:
229 case OffloadArch::SM_103a:
230 return 1030;
231 case OffloadArch::SM_110:
232 case OffloadArch::SM_110a:
233 return 1100;
234 case OffloadArch::SM_120:
235 case OffloadArch::SM_120a:
236 return 1200;
237 case OffloadArch::SM_121:
238 case OffloadArch::SM_121a:
239 return 1210;
240 default:
241 break;
242 }
243 llvm_unreachable("invalid NVIDIA GPU architecture");
244}
245
246bool IsNVIDIAAcceleratedOffloadArch(OffloadArch Arch) {
247 switch (Arch) {
248 case OffloadArch::SM_90a:
249 case OffloadArch::SM_100a:
250 case OffloadArch::SM_101a:
251 case OffloadArch::SM_103a:
252 case OffloadArch::SM_110a:
253 case OffloadArch::SM_120a:
254 case OffloadArch::SM_121a:
255 return true;
256 default:
257 return false;
258 }
259}
260} // namespace clang
261