1#include "clang/Basic/Cuda.h"
2
3#include "llvm/ADT/StringRef.h"
4#include "llvm/ADT/StringSwitch.h"
5#include "llvm/ADT/Twine.h"
6#include "llvm/Support/ErrorHandling.h"
7#include "llvm/Support/VersionTuple.h"
8
9namespace clang {
10
11const char *CudaVersionToString(CudaVersion V) {
12  switch (V) {
13  case CudaVersion::UNKNOWN:
14    return "unknown";
15  case CudaVersion::CUDA_70:
16    return "7.0";
17  case CudaVersion::CUDA_75:
18    return "7.5";
19  case CudaVersion::CUDA_80:
20    return "8.0";
21  case CudaVersion::CUDA_90:
22    return "9.0";
23  case CudaVersion::CUDA_91:
24    return "9.1";
25  case CudaVersion::CUDA_92:
26    return "9.2";
27  case CudaVersion::CUDA_100:
28    return "10.0";
29  case CudaVersion::CUDA_101:
30    return "10.1";
31  }
32  llvm_unreachable("invalid enum");
33}
34
35CudaVersion CudaStringToVersion(const llvm::Twine &S) {
36  return llvm::StringSwitch<CudaVersion>(S.str())
37      .Case("7.0", CudaVersion::CUDA_70)
38      .Case("7.5", CudaVersion::CUDA_75)
39      .Case("8.0", CudaVersion::CUDA_80)
40      .Case("9.0", CudaVersion::CUDA_90)
41      .Case("9.1", CudaVersion::CUDA_91)
42      .Case("9.2", CudaVersion::CUDA_92)
43      .Case("10.0", CudaVersion::CUDA_100)
44      .Case("10.1", CudaVersion::CUDA_101)
45      .Default(CudaVersion::UNKNOWN);
46}
47
48const char *CudaArchToString(CudaArch A) {
49  switch (A) {
50  case CudaArch::LAST:
51    break;
52  case CudaArch::UNKNOWN:
53    return "unknown";
54  case CudaArch::SM_20:
55    return "sm_20";
56  case CudaArch::SM_21:
57    return "sm_21";
58  case CudaArch::SM_30:
59    return "sm_30";
60  case CudaArch::SM_32:
61    return "sm_32";
62  case CudaArch::SM_35:
63    return "sm_35";
64  case CudaArch::SM_37:
65    return "sm_37";
66  case CudaArch::SM_50:
67    return "sm_50";
68  case CudaArch::SM_52:
69    return "sm_52";
70  case CudaArch::SM_53:
71    return "sm_53";
72  case CudaArch::SM_60:
73    return "sm_60";
74  case CudaArch::SM_61:
75    return "sm_61";
76  case CudaArch::SM_62:
77    return "sm_62";
78  case CudaArch::SM_70:
79    return "sm_70";
80  case CudaArch::SM_72:
81    return "sm_72";
82  case CudaArch::SM_75:
83    return "sm_75";
84  case CudaArch::GFX600: // tahiti
85    return "gfx600";
86  case CudaArch::GFX601: // pitcairn, verde, oland,hainan
87    return "gfx601";
88  case CudaArch::GFX700: // kaveri
89    return "gfx700";
90  case CudaArch::GFX701: // hawaii
91    return "gfx701";
92  case CudaArch::GFX702: // 290,290x,R390,R390x
93    return "gfx702";
94  case CudaArch::GFX703: // kabini mullins
95    return "gfx703";
96  case CudaArch::GFX704: // bonaire
97    return "gfx704";
98  case CudaArch::GFX801: // carrizo
99    return "gfx801";
100  case CudaArch::GFX802: // tonga,iceland
101    return "gfx802";
102  case CudaArch::GFX803: // fiji,polaris10
103    return "gfx803";
104  case CudaArch::GFX810: // stoney
105    return "gfx810";
106  case CudaArch::GFX900: // vega, instinct
107    return "gfx900";
108  case CudaArch::GFX902: // TBA
109    return "gfx902";
110  case CudaArch::GFX904: // TBA
111    return "gfx904";
112  case CudaArch::GFX906: // TBA
113    return "gfx906";
114  case CudaArch::GFX908: // TBA
115    return "gfx908";
116  case CudaArch::GFX909: // TBA
117    return "gfx909";
118  case CudaArch::GFX1010: // TBA
119    return "gfx1010";
120  case CudaArch::GFX1011: // TBA
121    return "gfx1011";
122  case CudaArch::GFX1012: // TBA
123    return "gfx1012";
124  }
125  llvm_unreachable("invalid enum");
126}
127
128CudaArch StringToCudaArch(llvm::StringRef S) {
129  return llvm::StringSwitch<CudaArch>(S)
130      .Case("sm_20", CudaArch::SM_20)
131      .Case("sm_21", CudaArch::SM_21)
132      .Case("sm_30", CudaArch::SM_30)
133      .Case("sm_32", CudaArch::SM_32)
134      .Case("sm_35", CudaArch::SM_35)
135      .Case("sm_37", CudaArch::SM_37)
136      .Case("sm_50", CudaArch::SM_50)
137      .Case("sm_52", CudaArch::SM_52)
138      .Case("sm_53", CudaArch::SM_53)
139      .Case("sm_60", CudaArch::SM_60)
140      .Case("sm_61", CudaArch::SM_61)
141      .Case("sm_62", CudaArch::SM_62)
142      .Case("sm_70", CudaArch::SM_70)
143      .Case("sm_72", CudaArch::SM_72)
144      .Case("sm_75", CudaArch::SM_75)
145      .Case("gfx600", CudaArch::GFX600)
146      .Case("gfx601", CudaArch::GFX601)
147      .Case("gfx700", CudaArch::GFX700)
148      .Case("gfx701", CudaArch::GFX701)
149      .Case("gfx702", CudaArch::GFX702)
150      .Case("gfx703", CudaArch::GFX703)
151      .Case("gfx704", CudaArch::GFX704)
152      .Case("gfx801", CudaArch::GFX801)
153      .Case("gfx802", CudaArch::GFX802)
154      .Case("gfx803", CudaArch::GFX803)
155      .Case("gfx810", CudaArch::GFX810)
156      .Case("gfx900", CudaArch::GFX900)
157      .Case("gfx902", CudaArch::GFX902)
158      .Case("gfx904", CudaArch::GFX904)
159      .Case("gfx906", CudaArch::GFX906)
160      .Case("gfx908", CudaArch::GFX908)
161      .Case("gfx909", CudaArch::GFX909)
162      .Case("gfx1010", CudaArch::GFX1010)
163      .Case("gfx1011", CudaArch::GFX1011)
164      .Case("gfx1012", CudaArch::GFX1012)
165      .Default(CudaArch::UNKNOWN);
166}
167
168const char *CudaVirtualArchToString(CudaVirtualArch A) {
169  switch (A) {
170  case CudaVirtualArch::UNKNOWN:
171    return "unknown";
172  case CudaVirtualArch::COMPUTE_20:
173    return "compute_20";
174  case CudaVirtualArch::COMPUTE_30:
175    return "compute_30";
176  case CudaVirtualArch::COMPUTE_32:
177    return "compute_32";
178  case CudaVirtualArch::COMPUTE_35:
179    return "compute_35";
180  case CudaVirtualArch::COMPUTE_37:
181    return "compute_37";
182  case CudaVirtualArch::COMPUTE_50:
183    return "compute_50";
184  case CudaVirtualArch::COMPUTE_52:
185    return "compute_52";
186  case CudaVirtualArch::COMPUTE_53:
187    return "compute_53";
188  case CudaVirtualArch::COMPUTE_60:
189    return "compute_60";
190  case CudaVirtualArch::COMPUTE_61:
191    return "compute_61";
192  case CudaVirtualArch::COMPUTE_62:
193    return "compute_62";
194  case CudaVirtualArch::COMPUTE_70:
195    return "compute_70";
196  case CudaVirtualArch::COMPUTE_72:
197    return "compute_72";
198  case CudaVirtualArch::COMPUTE_75:
199    return "compute_75";
200  case CudaVirtualArch::COMPUTE_AMDGCN:
201    return "compute_amdgcn";
202  }
203  llvm_unreachable("invalid enum");
204}
205
206CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
207  return llvm::StringSwitch<CudaVirtualArch>(S)
208      .Case("compute_20", CudaVirtualArch::COMPUTE_20)
209      .Case("compute_30", CudaVirtualArch::COMPUTE_30)
210      .Case("compute_32", CudaVirtualArch::COMPUTE_32)
211      .Case("compute_35", CudaVirtualArch::COMPUTE_35)
212      .Case("compute_37", CudaVirtualArch::COMPUTE_37)
213      .Case("compute_50", CudaVirtualArch::COMPUTE_50)
214      .Case("compute_52", CudaVirtualArch::COMPUTE_52)
215      .Case("compute_53", CudaVirtualArch::COMPUTE_53)
216      .Case("compute_60", CudaVirtualArch::COMPUTE_60)
217      .Case("compute_61", CudaVirtualArch::COMPUTE_61)
218      .Case("compute_62", CudaVirtualArch::COMPUTE_62)
219      .Case("compute_70", CudaVirtualArch::COMPUTE_70)
220      .Case("compute_72", CudaVirtualArch::COMPUTE_72)
221      .Case("compute_75", CudaVirtualArch::COMPUTE_75)
222      .Case("compute_amdgcn", CudaVirtualArch::COMPUTE_AMDGCN)
223      .Default(CudaVirtualArch::UNKNOWN);
224}
225
226CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
227  switch (A) {
228  case CudaArch::LAST:
229    break;
230  case CudaArch::UNKNOWN:
231    return CudaVirtualArch::UNKNOWN;
232  case CudaArch::SM_20:
233  case CudaArch::SM_21:
234    return CudaVirtualArch::COMPUTE_20;
235  case CudaArch::SM_30:
236    return CudaVirtualArch::COMPUTE_30;
237  case CudaArch::SM_32:
238    return CudaVirtualArch::COMPUTE_32;
239  case CudaArch::SM_35:
240    return CudaVirtualArch::COMPUTE_35;
241  case CudaArch::SM_37:
242    return CudaVirtualArch::COMPUTE_37;
243  case CudaArch::SM_50:
244    return CudaVirtualArch::COMPUTE_50;
245  case CudaArch::SM_52:
246    return CudaVirtualArch::COMPUTE_52;
247  case CudaArch::SM_53:
248    return CudaVirtualArch::COMPUTE_53;
249  case CudaArch::SM_60:
250    return CudaVirtualArch::COMPUTE_60;
251  case CudaArch::SM_61:
252    return CudaVirtualArch::COMPUTE_61;
253  case CudaArch::SM_62:
254    return CudaVirtualArch::COMPUTE_62;
255  case CudaArch::SM_70:
256    return CudaVirtualArch::COMPUTE_70;
257  case CudaArch::SM_72:
258    return CudaVirtualArch::COMPUTE_72;
259  case CudaArch::SM_75:
260    return CudaVirtualArch::COMPUTE_75;
261  case CudaArch::GFX600:
262  case CudaArch::GFX601:
263  case CudaArch::GFX700:
264  case CudaArch::GFX701:
265  case CudaArch::GFX702:
266  case CudaArch::GFX703:
267  case CudaArch::GFX704:
268  case CudaArch::GFX801:
269  case CudaArch::GFX802:
270  case CudaArch::GFX803:
271  case CudaArch::GFX810:
272  case CudaArch::GFX900:
273  case CudaArch::GFX902:
274  case CudaArch::GFX904:
275  case CudaArch::GFX906:
276  case CudaArch::GFX908:
277  case CudaArch::GFX909:
278  case CudaArch::GFX1010:
279  case CudaArch::GFX1011:
280  case CudaArch::GFX1012:
281    return CudaVirtualArch::COMPUTE_AMDGCN;
282  }
283  llvm_unreachable("invalid enum");
284}
285
286CudaVersion MinVersionForCudaArch(CudaArch A) {
287  switch (A) {
288  case CudaArch::LAST:
289    break;
290  case CudaArch::UNKNOWN:
291    return CudaVersion::UNKNOWN;
292  case CudaArch::SM_20:
293  case CudaArch::SM_21:
294  case CudaArch::SM_30:
295  case CudaArch::SM_32:
296  case CudaArch::SM_35:
297  case CudaArch::SM_37:
298  case CudaArch::SM_50:
299  case CudaArch::SM_52:
300  case CudaArch::SM_53:
301    return CudaVersion::CUDA_70;
302  case CudaArch::SM_60:
303  case CudaArch::SM_61:
304  case CudaArch::SM_62:
305    return CudaVersion::CUDA_80;
306  case CudaArch::SM_70:
307    return CudaVersion::CUDA_90;
308  case CudaArch::SM_72:
309    return CudaVersion::CUDA_91;
310  case CudaArch::SM_75:
311    return CudaVersion::CUDA_100;
312  case CudaArch::GFX600:
313  case CudaArch::GFX601:
314  case CudaArch::GFX700:
315  case CudaArch::GFX701:
316  case CudaArch::GFX702:
317  case CudaArch::GFX703:
318  case CudaArch::GFX704:
319  case CudaArch::GFX801:
320  case CudaArch::GFX802:
321  case CudaArch::GFX803:
322  case CudaArch::GFX810:
323  case CudaArch::GFX900:
324  case CudaArch::GFX902:
325  case CudaArch::GFX904:
326  case CudaArch::GFX906:
327  case CudaArch::GFX908:
328  case CudaArch::GFX909:
329  case CudaArch::GFX1010:
330  case CudaArch::GFX1011:
331  case CudaArch::GFX1012:
332    return CudaVersion::CUDA_70;
333  }
334  llvm_unreachable("invalid enum");
335}
336
337CudaVersion MaxVersionForCudaArch(CudaArch A) {
338  switch (A) {
339  case CudaArch::UNKNOWN:
340    return CudaVersion::UNKNOWN;
341  case CudaArch::SM_20:
342  case CudaArch::SM_21:
343  case CudaArch::GFX600:
344  case CudaArch::GFX601:
345  case CudaArch::GFX700:
346  case CudaArch::GFX701:
347  case CudaArch::GFX702:
348  case CudaArch::GFX703:
349  case CudaArch::GFX704:
350  case CudaArch::GFX801:
351  case CudaArch::GFX802:
352  case CudaArch::GFX803:
353  case CudaArch::GFX810:
354  case CudaArch::GFX900:
355  case CudaArch::GFX902:
356  case CudaArch::GFX1010:
357  case CudaArch::GFX1011:
358  case CudaArch::GFX1012:
359    return CudaVersion::CUDA_80;
360  default:
361    return CudaVersion::LATEST;
362  }
363}
364
365static CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
366  int IVer =
367      Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
368  switch(IVer) {
369  case 70:
370    return CudaVersion::CUDA_70;
371  case 75:
372    return CudaVersion::CUDA_75;
373  case 80:
374    return CudaVersion::CUDA_80;
375  case 90:
376    return CudaVersion::CUDA_90;
377  case 91:
378    return CudaVersion::CUDA_91;
379  case 92:
380    return CudaVersion::CUDA_92;
381  case 100:
382    return CudaVersion::CUDA_100;
383  case 101:
384    return CudaVersion::CUDA_101;
385  default:
386    return CudaVersion::UNKNOWN;
387  }
388}
389
390bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
391  return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
392}
393
394bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
395  switch (Feature) {
396  case CudaFeature::CUDA_USES_NEW_LAUNCH:
397    return Version >= CudaVersion::CUDA_92;
398  case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
399    return Version >= CudaVersion::CUDA_101;
400  }
401  llvm_unreachable("Unknown CUDA feature.");
402}
403} // namespace clang
404