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::GFX909: // TBA
113     return "gfx909";
114   }
115   llvm_unreachable("invalid enum");
116 }
117 
118 CudaArch StringToCudaArch(llvm::StringRef S) {
119   return llvm::StringSwitch<CudaArch>(S)
120       .Case("sm_20", CudaArch::SM_20)
121       .Case("sm_21", CudaArch::SM_21)
122       .Case("sm_30", CudaArch::SM_30)
123       .Case("sm_32", CudaArch::SM_32)
124       .Case("sm_35", CudaArch::SM_35)
125       .Case("sm_37", CudaArch::SM_37)
126       .Case("sm_50", CudaArch::SM_50)
127       .Case("sm_52", CudaArch::SM_52)
128       .Case("sm_53", CudaArch::SM_53)
129       .Case("sm_60", CudaArch::SM_60)
130       .Case("sm_61", CudaArch::SM_61)
131       .Case("sm_62", CudaArch::SM_62)
132       .Case("sm_70", CudaArch::SM_70)
133       .Case("sm_72", CudaArch::SM_72)
134       .Case("sm_75", CudaArch::SM_75)
135       .Case("gfx600", CudaArch::GFX600)
136       .Case("gfx601", CudaArch::GFX601)
137       .Case("gfx700", CudaArch::GFX700)
138       .Case("gfx701", CudaArch::GFX701)
139       .Case("gfx702", CudaArch::GFX702)
140       .Case("gfx703", CudaArch::GFX703)
141       .Case("gfx704", CudaArch::GFX704)
142       .Case("gfx801", CudaArch::GFX801)
143       .Case("gfx802", CudaArch::GFX802)
144       .Case("gfx803", CudaArch::GFX803)
145       .Case("gfx810", CudaArch::GFX810)
146       .Case("gfx900", CudaArch::GFX900)
147       .Case("gfx902", CudaArch::GFX902)
148       .Case("gfx904", CudaArch::GFX904)
149       .Case("gfx906", CudaArch::GFX906)
150       .Case("gfx909", CudaArch::GFX909)
151       .Default(CudaArch::UNKNOWN);
152 }
153 
154 const char *CudaVirtualArchToString(CudaVirtualArch A) {
155   switch (A) {
156   case CudaVirtualArch::UNKNOWN:
157     return "unknown";
158   case CudaVirtualArch::COMPUTE_20:
159     return "compute_20";
160   case CudaVirtualArch::COMPUTE_30:
161     return "compute_30";
162   case CudaVirtualArch::COMPUTE_32:
163     return "compute_32";
164   case CudaVirtualArch::COMPUTE_35:
165     return "compute_35";
166   case CudaVirtualArch::COMPUTE_37:
167     return "compute_37";
168   case CudaVirtualArch::COMPUTE_50:
169     return "compute_50";
170   case CudaVirtualArch::COMPUTE_52:
171     return "compute_52";
172   case CudaVirtualArch::COMPUTE_53:
173     return "compute_53";
174   case CudaVirtualArch::COMPUTE_60:
175     return "compute_60";
176   case CudaVirtualArch::COMPUTE_61:
177     return "compute_61";
178   case CudaVirtualArch::COMPUTE_62:
179     return "compute_62";
180   case CudaVirtualArch::COMPUTE_70:
181     return "compute_70";
182   case CudaVirtualArch::COMPUTE_72:
183     return "compute_72";
184   case CudaVirtualArch::COMPUTE_75:
185     return "compute_75";
186   case CudaVirtualArch::COMPUTE_AMDGCN:
187     return "compute_amdgcn";
188   }
189   llvm_unreachable("invalid enum");
190 }
191 
192 CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
193   return llvm::StringSwitch<CudaVirtualArch>(S)
194       .Case("compute_20", CudaVirtualArch::COMPUTE_20)
195       .Case("compute_30", CudaVirtualArch::COMPUTE_30)
196       .Case("compute_32", CudaVirtualArch::COMPUTE_32)
197       .Case("compute_35", CudaVirtualArch::COMPUTE_35)
198       .Case("compute_37", CudaVirtualArch::COMPUTE_37)
199       .Case("compute_50", CudaVirtualArch::COMPUTE_50)
200       .Case("compute_52", CudaVirtualArch::COMPUTE_52)
201       .Case("compute_53", CudaVirtualArch::COMPUTE_53)
202       .Case("compute_60", CudaVirtualArch::COMPUTE_60)
203       .Case("compute_61", CudaVirtualArch::COMPUTE_61)
204       .Case("compute_62", CudaVirtualArch::COMPUTE_62)
205       .Case("compute_70", CudaVirtualArch::COMPUTE_70)
206       .Case("compute_72", CudaVirtualArch::COMPUTE_72)
207       .Case("compute_75", CudaVirtualArch::COMPUTE_75)
208       .Case("compute_amdgcn", CudaVirtualArch::COMPUTE_AMDGCN)
209       .Default(CudaVirtualArch::UNKNOWN);
210 }
211 
212 CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
213   switch (A) {
214   case CudaArch::LAST:
215     break;
216   case CudaArch::UNKNOWN:
217     return CudaVirtualArch::UNKNOWN;
218   case CudaArch::SM_20:
219   case CudaArch::SM_21:
220     return CudaVirtualArch::COMPUTE_20;
221   case CudaArch::SM_30:
222     return CudaVirtualArch::COMPUTE_30;
223   case CudaArch::SM_32:
224     return CudaVirtualArch::COMPUTE_32;
225   case CudaArch::SM_35:
226     return CudaVirtualArch::COMPUTE_35;
227   case CudaArch::SM_37:
228     return CudaVirtualArch::COMPUTE_37;
229   case CudaArch::SM_50:
230     return CudaVirtualArch::COMPUTE_50;
231   case CudaArch::SM_52:
232     return CudaVirtualArch::COMPUTE_52;
233   case CudaArch::SM_53:
234     return CudaVirtualArch::COMPUTE_53;
235   case CudaArch::SM_60:
236     return CudaVirtualArch::COMPUTE_60;
237   case CudaArch::SM_61:
238     return CudaVirtualArch::COMPUTE_61;
239   case CudaArch::SM_62:
240     return CudaVirtualArch::COMPUTE_62;
241   case CudaArch::SM_70:
242     return CudaVirtualArch::COMPUTE_70;
243   case CudaArch::SM_72:
244     return CudaVirtualArch::COMPUTE_72;
245   case CudaArch::SM_75:
246     return CudaVirtualArch::COMPUTE_75;
247   case CudaArch::GFX600:
248   case CudaArch::GFX601:
249   case CudaArch::GFX700:
250   case CudaArch::GFX701:
251   case CudaArch::GFX702:
252   case CudaArch::GFX703:
253   case CudaArch::GFX704:
254   case CudaArch::GFX801:
255   case CudaArch::GFX802:
256   case CudaArch::GFX803:
257   case CudaArch::GFX810:
258   case CudaArch::GFX900:
259   case CudaArch::GFX902:
260   case CudaArch::GFX904:
261   case CudaArch::GFX906:
262   case CudaArch::GFX909:
263     return CudaVirtualArch::COMPUTE_AMDGCN;
264   }
265   llvm_unreachable("invalid enum");
266 }
267 
268 CudaVersion MinVersionForCudaArch(CudaArch A) {
269   switch (A) {
270   case CudaArch::LAST:
271     break;
272   case CudaArch::UNKNOWN:
273     return CudaVersion::UNKNOWN;
274   case CudaArch::SM_20:
275   case CudaArch::SM_21:
276   case CudaArch::SM_30:
277   case CudaArch::SM_32:
278   case CudaArch::SM_35:
279   case CudaArch::SM_37:
280   case CudaArch::SM_50:
281   case CudaArch::SM_52:
282   case CudaArch::SM_53:
283     return CudaVersion::CUDA_70;
284   case CudaArch::SM_60:
285   case CudaArch::SM_61:
286   case CudaArch::SM_62:
287     return CudaVersion::CUDA_80;
288   case CudaArch::SM_70:
289     return CudaVersion::CUDA_90;
290   case CudaArch::SM_72:
291     return CudaVersion::CUDA_91;
292   case CudaArch::SM_75:
293     return CudaVersion::CUDA_100;
294   case CudaArch::GFX600:
295   case CudaArch::GFX601:
296   case CudaArch::GFX700:
297   case CudaArch::GFX701:
298   case CudaArch::GFX702:
299   case CudaArch::GFX703:
300   case CudaArch::GFX704:
301   case CudaArch::GFX801:
302   case CudaArch::GFX802:
303   case CudaArch::GFX803:
304   case CudaArch::GFX810:
305   case CudaArch::GFX900:
306   case CudaArch::GFX902:
307   case CudaArch::GFX904:
308   case CudaArch::GFX906:
309   case CudaArch::GFX909:
310     return CudaVersion::CUDA_70;
311   }
312   llvm_unreachable("invalid enum");
313 }
314 
315 CudaVersion MaxVersionForCudaArch(CudaArch A) {
316   switch (A) {
317   case CudaArch::UNKNOWN:
318     return CudaVersion::UNKNOWN;
319   case CudaArch::SM_20:
320   case CudaArch::SM_21:
321   case CudaArch::GFX600:
322   case CudaArch::GFX601:
323   case CudaArch::GFX700:
324   case CudaArch::GFX701:
325   case CudaArch::GFX702:
326   case CudaArch::GFX703:
327   case CudaArch::GFX704:
328   case CudaArch::GFX801:
329   case CudaArch::GFX802:
330   case CudaArch::GFX803:
331   case CudaArch::GFX810:
332   case CudaArch::GFX900:
333   case CudaArch::GFX902:
334     return CudaVersion::CUDA_80;
335   default:
336     return CudaVersion::LATEST;
337   }
338 }
339 
340 static CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
341   int IVer =
342       Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
343   switch(IVer) {
344   case 70:
345     return CudaVersion::CUDA_70;
346   case 75:
347     return CudaVersion::CUDA_75;
348   case 80:
349     return CudaVersion::CUDA_80;
350   case 90:
351     return CudaVersion::CUDA_90;
352   case 91:
353     return CudaVersion::CUDA_91;
354   case 92:
355     return CudaVersion::CUDA_92;
356   case 100:
357     return CudaVersion::CUDA_100;
358   case 101:
359     return CudaVersion::CUDA_101;
360   default:
361     return CudaVersion::UNKNOWN;
362   }
363 }
364 
365 bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
366   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
367 }
368 
369 bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
370   switch (Feature) {
371   case CudaFeature::CUDA_USES_NEW_LAUNCH:
372     return Version >= CudaVersion::CUDA_92;
373   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
374     return Version >= CudaVersion::CUDA_101;
375   }
376   llvm_unreachable("Unknown CUDA feature.");
377 }
378 } // namespace clang
379