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