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