xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Cuda.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric #include "clang/Basic/Cuda.h"
20b57cec5SDimitry Andric 
30b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
40b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
513138422SDimitry Andric #include "llvm/ADT/Twine.h"
60b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
70b57cec5SDimitry Andric #include "llvm/Support/VersionTuple.h"
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric namespace clang {
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric const char *CudaVersionToString(CudaVersion V) {
120b57cec5SDimitry Andric   switch (V) {
130b57cec5SDimitry Andric   case CudaVersion::UNKNOWN:
140b57cec5SDimitry Andric     return "unknown";
150b57cec5SDimitry Andric   case CudaVersion::CUDA_70:
160b57cec5SDimitry Andric     return "7.0";
170b57cec5SDimitry Andric   case CudaVersion::CUDA_75:
180b57cec5SDimitry Andric     return "7.5";
190b57cec5SDimitry Andric   case CudaVersion::CUDA_80:
200b57cec5SDimitry Andric     return "8.0";
210b57cec5SDimitry Andric   case CudaVersion::CUDA_90:
220b57cec5SDimitry Andric     return "9.0";
230b57cec5SDimitry Andric   case CudaVersion::CUDA_91:
240b57cec5SDimitry Andric     return "9.1";
250b57cec5SDimitry Andric   case CudaVersion::CUDA_92:
260b57cec5SDimitry Andric     return "9.2";
270b57cec5SDimitry Andric   case CudaVersion::CUDA_100:
280b57cec5SDimitry Andric     return "10.0";
290b57cec5SDimitry Andric   case CudaVersion::CUDA_101:
300b57cec5SDimitry Andric     return "10.1";
31*5ffd83dbSDimitry Andric   case CudaVersion::CUDA_102:
32*5ffd83dbSDimitry Andric     return "10.2";
33*5ffd83dbSDimitry Andric   case CudaVersion::CUDA_110:
34*5ffd83dbSDimitry Andric     return "11.0";
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric   llvm_unreachable("invalid enum");
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
3913138422SDimitry Andric CudaVersion CudaStringToVersion(const llvm::Twine &S) {
4013138422SDimitry Andric   return llvm::StringSwitch<CudaVersion>(S.str())
410b57cec5SDimitry Andric       .Case("7.0", CudaVersion::CUDA_70)
420b57cec5SDimitry Andric       .Case("7.5", CudaVersion::CUDA_75)
430b57cec5SDimitry Andric       .Case("8.0", CudaVersion::CUDA_80)
440b57cec5SDimitry Andric       .Case("9.0", CudaVersion::CUDA_90)
450b57cec5SDimitry Andric       .Case("9.1", CudaVersion::CUDA_91)
460b57cec5SDimitry Andric       .Case("9.2", CudaVersion::CUDA_92)
470b57cec5SDimitry Andric       .Case("10.0", CudaVersion::CUDA_100)
4813138422SDimitry Andric       .Case("10.1", CudaVersion::CUDA_101)
49*5ffd83dbSDimitry Andric       .Case("10.2", CudaVersion::CUDA_102)
50*5ffd83dbSDimitry Andric       .Case("11.0", CudaVersion::CUDA_110)
5113138422SDimitry Andric       .Default(CudaVersion::UNKNOWN);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
54*5ffd83dbSDimitry Andric struct CudaArchToStringMap {
55*5ffd83dbSDimitry Andric   CudaArch arch;
56*5ffd83dbSDimitry Andric   const char *arch_name;
57*5ffd83dbSDimitry Andric   const char *virtual_arch_name;
58*5ffd83dbSDimitry Andric };
59*5ffd83dbSDimitry Andric 
60*5ffd83dbSDimitry Andric #define SM2(sm, ca)                                                            \
61*5ffd83dbSDimitry Andric   { CudaArch::SM_##sm, "sm_" #sm, ca }
62*5ffd83dbSDimitry Andric #define SM(sm) SM2(sm, "compute_" #sm)
63*5ffd83dbSDimitry Andric #define GFX(gpu)                                                               \
64*5ffd83dbSDimitry Andric   { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
65*5ffd83dbSDimitry Andric CudaArchToStringMap arch_names[] = {
66*5ffd83dbSDimitry Andric     // clang-format off
67*5ffd83dbSDimitry Andric     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
68*5ffd83dbSDimitry Andric     SM(30), SM(32), SM(35), SM(37),  // Kepler
69*5ffd83dbSDimitry Andric     SM(50), SM(52), SM(53),          // Maxwell
70*5ffd83dbSDimitry Andric     SM(60), SM(61), SM(62),          // Pascal
71*5ffd83dbSDimitry Andric     SM(70), SM(72),                  // Volta
72*5ffd83dbSDimitry Andric     SM(75),                          // Turing
73*5ffd83dbSDimitry Andric     SM(80),                          // Ampere
74*5ffd83dbSDimitry Andric     GFX(600), // tahiti
75*5ffd83dbSDimitry Andric     GFX(601), // pitcairn, verde, oland,hainan
76*5ffd83dbSDimitry Andric     GFX(700), // kaveri
77*5ffd83dbSDimitry Andric     GFX(701), // hawaii
78*5ffd83dbSDimitry Andric     GFX(702), // 290,290x,R390,R390x
79*5ffd83dbSDimitry Andric     GFX(703), // kabini mullins
80*5ffd83dbSDimitry Andric     GFX(704), // bonaire
81*5ffd83dbSDimitry Andric     GFX(801), // carrizo
82*5ffd83dbSDimitry Andric     GFX(802), // tonga,iceland
83*5ffd83dbSDimitry Andric     GFX(803), // fiji,polaris10
84*5ffd83dbSDimitry Andric     GFX(810), // stoney
85*5ffd83dbSDimitry Andric     GFX(900), // vega, instinct
86*5ffd83dbSDimitry Andric     GFX(902), GFX(904), GFX(906), GFX(908), GFX(909),
87*5ffd83dbSDimitry Andric     GFX(1010), GFX(1011), GFX(1012),
88*5ffd83dbSDimitry Andric     // clang-format on
89*5ffd83dbSDimitry Andric };
90*5ffd83dbSDimitry Andric #undef SM
91*5ffd83dbSDimitry Andric #undef SM2
92*5ffd83dbSDimitry Andric #undef GFX
93*5ffd83dbSDimitry Andric 
940b57cec5SDimitry Andric const char *CudaArchToString(CudaArch A) {
95*5ffd83dbSDimitry Andric   auto result = std::find_if(
96*5ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
97*5ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
98*5ffd83dbSDimitry Andric   if (result == std::end(arch_names))
990b57cec5SDimitry Andric     return "unknown";
100*5ffd83dbSDimitry Andric   return result->arch_name;
1010b57cec5SDimitry Andric }
102*5ffd83dbSDimitry Andric 
103*5ffd83dbSDimitry Andric const char *CudaArchToVirtualArchString(CudaArch A) {
104*5ffd83dbSDimitry Andric   auto result = std::find_if(
105*5ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
106*5ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
107*5ffd83dbSDimitry Andric   if (result == std::end(arch_names))
108*5ffd83dbSDimitry Andric     return "unknown";
109*5ffd83dbSDimitry Andric   return result->virtual_arch_name;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric CudaArch StringToCudaArch(llvm::StringRef S) {
113*5ffd83dbSDimitry Andric   auto result = std::find_if(
114*5ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
115*5ffd83dbSDimitry Andric       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
116*5ffd83dbSDimitry Andric   if (result == std::end(arch_names))
117*5ffd83dbSDimitry Andric     return CudaArch::UNKNOWN;
118*5ffd83dbSDimitry Andric   return result->arch;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric CudaVersion MinVersionForCudaArch(CudaArch A) {
122*5ffd83dbSDimitry Andric   if (A == CudaArch::UNKNOWN)
1230b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
124*5ffd83dbSDimitry Andric 
125*5ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
126*5ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
127*5ffd83dbSDimitry Andric     return CudaVersion::CUDA_70;
128*5ffd83dbSDimitry Andric 
129*5ffd83dbSDimitry Andric   switch (A) {
1300b57cec5SDimitry Andric   case CudaArch::SM_20:
1310b57cec5SDimitry Andric   case CudaArch::SM_21:
1320b57cec5SDimitry Andric   case CudaArch::SM_30:
1330b57cec5SDimitry Andric   case CudaArch::SM_32:
1340b57cec5SDimitry Andric   case CudaArch::SM_35:
1350b57cec5SDimitry Andric   case CudaArch::SM_37:
1360b57cec5SDimitry Andric   case CudaArch::SM_50:
1370b57cec5SDimitry Andric   case CudaArch::SM_52:
1380b57cec5SDimitry Andric   case CudaArch::SM_53:
1390b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
1400b57cec5SDimitry Andric   case CudaArch::SM_60:
1410b57cec5SDimitry Andric   case CudaArch::SM_61:
1420b57cec5SDimitry Andric   case CudaArch::SM_62:
1430b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1440b57cec5SDimitry Andric   case CudaArch::SM_70:
1450b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
1460b57cec5SDimitry Andric   case CudaArch::SM_72:
1470b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
1480b57cec5SDimitry Andric   case CudaArch::SM_75:
1490b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
150*5ffd83dbSDimitry Andric   case CudaArch::SM_80:
151*5ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
152*5ffd83dbSDimitry Andric   default:
1530b57cec5SDimitry Andric     llvm_unreachable("invalid enum");
1540b57cec5SDimitry Andric   }
155*5ffd83dbSDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric CudaVersion MaxVersionForCudaArch(CudaArch A) {
158*5ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
159*5ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
160*5ffd83dbSDimitry Andric     return CudaVersion::LATEST;
161*5ffd83dbSDimitry Andric 
1620b57cec5SDimitry Andric   switch (A) {
1630b57cec5SDimitry Andric   case CudaArch::UNKNOWN:
1640b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1650b57cec5SDimitry Andric   case CudaArch::SM_20:
1660b57cec5SDimitry Andric   case CudaArch::SM_21:
1670b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1680b57cec5SDimitry Andric   default:
1690b57cec5SDimitry Andric     return CudaVersion::LATEST;
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
173*5ffd83dbSDimitry Andric CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
1740b57cec5SDimitry Andric   int IVer =
1750b57cec5SDimitry Andric       Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
1760b57cec5SDimitry Andric   switch(IVer) {
1770b57cec5SDimitry Andric   case 70:
1780b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
1790b57cec5SDimitry Andric   case 75:
1800b57cec5SDimitry Andric     return CudaVersion::CUDA_75;
1810b57cec5SDimitry Andric   case 80:
1820b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1830b57cec5SDimitry Andric   case 90:
1840b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
1850b57cec5SDimitry Andric   case 91:
1860b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
1870b57cec5SDimitry Andric   case 92:
1880b57cec5SDimitry Andric     return CudaVersion::CUDA_92;
1890b57cec5SDimitry Andric   case 100:
1900b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
1910b57cec5SDimitry Andric   case 101:
1920b57cec5SDimitry Andric     return CudaVersion::CUDA_101;
193*5ffd83dbSDimitry Andric   case 102:
194*5ffd83dbSDimitry Andric     return CudaVersion::CUDA_102;
195*5ffd83dbSDimitry Andric   case 110:
196*5ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
1970b57cec5SDimitry Andric   default:
1980b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
2030b57cec5SDimitry Andric   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2070b57cec5SDimitry Andric   switch (Feature) {
2080b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_NEW_LAUNCH:
2090b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_92;
2100b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2110b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_101;
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric   llvm_unreachable("Unknown CUDA feature.");
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric } // namespace clang
216