xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Cuda.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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";
315ffd83dbSDimitry Andric   case CudaVersion::CUDA_102:
325ffd83dbSDimitry Andric     return "10.2";
335ffd83dbSDimitry Andric   case CudaVersion::CUDA_110:
345ffd83dbSDimitry Andric     return "11.0";
35*fe6060f1SDimitry Andric   case CudaVersion::CUDA_111:
36*fe6060f1SDimitry Andric     return "11.1";
37*fe6060f1SDimitry Andric   case CudaVersion::CUDA_112:
38*fe6060f1SDimitry Andric     return "11.2";
390b57cec5SDimitry Andric   }
400b57cec5SDimitry Andric   llvm_unreachable("invalid enum");
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
4313138422SDimitry Andric CudaVersion CudaStringToVersion(const llvm::Twine &S) {
4413138422SDimitry Andric   return llvm::StringSwitch<CudaVersion>(S.str())
450b57cec5SDimitry Andric       .Case("7.0", CudaVersion::CUDA_70)
460b57cec5SDimitry Andric       .Case("7.5", CudaVersion::CUDA_75)
470b57cec5SDimitry Andric       .Case("8.0", CudaVersion::CUDA_80)
480b57cec5SDimitry Andric       .Case("9.0", CudaVersion::CUDA_90)
490b57cec5SDimitry Andric       .Case("9.1", CudaVersion::CUDA_91)
500b57cec5SDimitry Andric       .Case("9.2", CudaVersion::CUDA_92)
510b57cec5SDimitry Andric       .Case("10.0", CudaVersion::CUDA_100)
5213138422SDimitry Andric       .Case("10.1", CudaVersion::CUDA_101)
535ffd83dbSDimitry Andric       .Case("10.2", CudaVersion::CUDA_102)
545ffd83dbSDimitry Andric       .Case("11.0", CudaVersion::CUDA_110)
55*fe6060f1SDimitry Andric       .Case("11.1", CudaVersion::CUDA_111)
56*fe6060f1SDimitry Andric       .Case("11.2", CudaVersion::CUDA_112)
5713138422SDimitry Andric       .Default(CudaVersion::UNKNOWN);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
60*fe6060f1SDimitry Andric namespace {
615ffd83dbSDimitry Andric struct CudaArchToStringMap {
625ffd83dbSDimitry Andric   CudaArch arch;
635ffd83dbSDimitry Andric   const char *arch_name;
645ffd83dbSDimitry Andric   const char *virtual_arch_name;
655ffd83dbSDimitry Andric };
66*fe6060f1SDimitry Andric } // namespace
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric #define SM2(sm, ca)                                                            \
695ffd83dbSDimitry Andric   { CudaArch::SM_##sm, "sm_" #sm, ca }
705ffd83dbSDimitry Andric #define SM(sm) SM2(sm, "compute_" #sm)
715ffd83dbSDimitry Andric #define GFX(gpu)                                                               \
725ffd83dbSDimitry Andric   { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
73*fe6060f1SDimitry Andric static const CudaArchToStringMap arch_names[] = {
745ffd83dbSDimitry Andric     // clang-format off
75e8d8bef9SDimitry Andric     {CudaArch::UNUSED, "", ""},
765ffd83dbSDimitry Andric     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
775ffd83dbSDimitry Andric     SM(30), SM(32), SM(35), SM(37),  // Kepler
785ffd83dbSDimitry Andric     SM(50), SM(52), SM(53),          // Maxwell
795ffd83dbSDimitry Andric     SM(60), SM(61), SM(62),          // Pascal
805ffd83dbSDimitry Andric     SM(70), SM(72),                  // Volta
815ffd83dbSDimitry Andric     SM(75),                          // Turing
82*fe6060f1SDimitry Andric     SM(80), SM(86),                  // Ampere
83e8d8bef9SDimitry Andric     GFX(600),  // gfx600
84e8d8bef9SDimitry Andric     GFX(601),  // gfx601
85e8d8bef9SDimitry Andric     GFX(602),  // gfx602
86e8d8bef9SDimitry Andric     GFX(700),  // gfx700
87e8d8bef9SDimitry Andric     GFX(701),  // gfx701
88e8d8bef9SDimitry Andric     GFX(702),  // gfx702
89e8d8bef9SDimitry Andric     GFX(703),  // gfx703
90e8d8bef9SDimitry Andric     GFX(704),  // gfx704
91e8d8bef9SDimitry Andric     GFX(705),  // gfx705
92e8d8bef9SDimitry Andric     GFX(801),  // gfx801
93e8d8bef9SDimitry Andric     GFX(802),  // gfx802
94e8d8bef9SDimitry Andric     GFX(803),  // gfx803
95e8d8bef9SDimitry Andric     GFX(805),  // gfx805
96e8d8bef9SDimitry Andric     GFX(810),  // gfx810
97e8d8bef9SDimitry Andric     GFX(900),  // gfx900
98e8d8bef9SDimitry Andric     GFX(902),  // gfx902
99e8d8bef9SDimitry Andric     GFX(904),  // gfx903
100e8d8bef9SDimitry Andric     GFX(906),  // gfx906
101e8d8bef9SDimitry Andric     GFX(908),  // gfx908
102e8d8bef9SDimitry Andric     GFX(909),  // gfx909
103*fe6060f1SDimitry Andric     GFX(90a),  // gfx90a
104e8d8bef9SDimitry Andric     GFX(90c),  // gfx90c
105e8d8bef9SDimitry Andric     GFX(1010), // gfx1010
106e8d8bef9SDimitry Andric     GFX(1011), // gfx1011
107e8d8bef9SDimitry Andric     GFX(1012), // gfx1012
108*fe6060f1SDimitry Andric     GFX(1013), // gfx1013
109e8d8bef9SDimitry Andric     GFX(1030), // gfx1030
110e8d8bef9SDimitry Andric     GFX(1031), // gfx1031
111e8d8bef9SDimitry Andric     GFX(1032), // gfx1032
112e8d8bef9SDimitry Andric     GFX(1033), // gfx1033
113*fe6060f1SDimitry Andric     GFX(1034), // gfx1034
114*fe6060f1SDimitry Andric     GFX(1035), // gfx1035
1155ffd83dbSDimitry Andric     // clang-format on
1165ffd83dbSDimitry Andric };
1175ffd83dbSDimitry Andric #undef SM
1185ffd83dbSDimitry Andric #undef SM2
1195ffd83dbSDimitry Andric #undef GFX
1205ffd83dbSDimitry Andric 
1210b57cec5SDimitry Andric const char *CudaArchToString(CudaArch A) {
1225ffd83dbSDimitry Andric   auto result = std::find_if(
1235ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1245ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
1255ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1260b57cec5SDimitry Andric     return "unknown";
1275ffd83dbSDimitry Andric   return result->arch_name;
1280b57cec5SDimitry Andric }
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric const char *CudaArchToVirtualArchString(CudaArch A) {
1315ffd83dbSDimitry Andric   auto result = std::find_if(
1325ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1335ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
1345ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1355ffd83dbSDimitry Andric     return "unknown";
1365ffd83dbSDimitry Andric   return result->virtual_arch_name;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric CudaArch StringToCudaArch(llvm::StringRef S) {
1405ffd83dbSDimitry Andric   auto result = std::find_if(
1415ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1425ffd83dbSDimitry Andric       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
1435ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1445ffd83dbSDimitry Andric     return CudaArch::UNKNOWN;
1455ffd83dbSDimitry Andric   return result->arch;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric CudaVersion MinVersionForCudaArch(CudaArch A) {
1495ffd83dbSDimitry Andric   if (A == CudaArch::UNKNOWN)
1500b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1515ffd83dbSDimitry Andric 
1525ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
1535ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
1545ffd83dbSDimitry Andric     return CudaVersion::CUDA_70;
1555ffd83dbSDimitry Andric 
1565ffd83dbSDimitry Andric   switch (A) {
1570b57cec5SDimitry Andric   case CudaArch::SM_20:
1580b57cec5SDimitry Andric   case CudaArch::SM_21:
1590b57cec5SDimitry Andric   case CudaArch::SM_30:
1600b57cec5SDimitry Andric   case CudaArch::SM_32:
1610b57cec5SDimitry Andric   case CudaArch::SM_35:
1620b57cec5SDimitry Andric   case CudaArch::SM_37:
1630b57cec5SDimitry Andric   case CudaArch::SM_50:
1640b57cec5SDimitry Andric   case CudaArch::SM_52:
1650b57cec5SDimitry Andric   case CudaArch::SM_53:
1660b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
1670b57cec5SDimitry Andric   case CudaArch::SM_60:
1680b57cec5SDimitry Andric   case CudaArch::SM_61:
1690b57cec5SDimitry Andric   case CudaArch::SM_62:
1700b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1710b57cec5SDimitry Andric   case CudaArch::SM_70:
1720b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
1730b57cec5SDimitry Andric   case CudaArch::SM_72:
1740b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
1750b57cec5SDimitry Andric   case CudaArch::SM_75:
1760b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
1775ffd83dbSDimitry Andric   case CudaArch::SM_80:
1785ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
179*fe6060f1SDimitry Andric   case CudaArch::SM_86:
180*fe6060f1SDimitry Andric     return CudaVersion::CUDA_111;
1815ffd83dbSDimitry Andric   default:
1820b57cec5SDimitry Andric     llvm_unreachable("invalid enum");
1830b57cec5SDimitry Andric   }
1845ffd83dbSDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric CudaVersion MaxVersionForCudaArch(CudaArch A) {
1875ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
1885ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
1895ffd83dbSDimitry Andric     return CudaVersion::LATEST;
1905ffd83dbSDimitry Andric 
1910b57cec5SDimitry Andric   switch (A) {
1920b57cec5SDimitry Andric   case CudaArch::UNKNOWN:
1930b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1940b57cec5SDimitry Andric   case CudaArch::SM_20:
1950b57cec5SDimitry Andric   case CudaArch::SM_21:
1960b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1970b57cec5SDimitry Andric   default:
1980b57cec5SDimitry Andric     return CudaVersion::LATEST;
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2025ffd83dbSDimitry Andric CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
2030b57cec5SDimitry Andric   int IVer =
2040b57cec5SDimitry Andric       Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
2050b57cec5SDimitry Andric   switch(IVer) {
2060b57cec5SDimitry Andric   case 70:
2070b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
2080b57cec5SDimitry Andric   case 75:
2090b57cec5SDimitry Andric     return CudaVersion::CUDA_75;
2100b57cec5SDimitry Andric   case 80:
2110b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
2120b57cec5SDimitry Andric   case 90:
2130b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
2140b57cec5SDimitry Andric   case 91:
2150b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
2160b57cec5SDimitry Andric   case 92:
2170b57cec5SDimitry Andric     return CudaVersion::CUDA_92;
2180b57cec5SDimitry Andric   case 100:
2190b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
2200b57cec5SDimitry Andric   case 101:
2210b57cec5SDimitry Andric     return CudaVersion::CUDA_101;
2225ffd83dbSDimitry Andric   case 102:
2235ffd83dbSDimitry Andric     return CudaVersion::CUDA_102;
2245ffd83dbSDimitry Andric   case 110:
2255ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
226*fe6060f1SDimitry Andric   case 111:
227*fe6060f1SDimitry Andric     return CudaVersion::CUDA_111;
228*fe6060f1SDimitry Andric   case 112:
229*fe6060f1SDimitry Andric     return CudaVersion::CUDA_112;
2300b57cec5SDimitry Andric   default:
2310b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
2360b57cec5SDimitry Andric   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2400b57cec5SDimitry Andric   switch (Feature) {
2410b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_NEW_LAUNCH:
2420b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_92;
2430b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2440b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_101;
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   llvm_unreachable("Unknown CUDA feature.");
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric } // namespace clang
249