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