162907617SJustin Lebar #include "clang/Basic/Cuda.h"
262907617SJustin Lebar 
362907617SJustin Lebar #include "llvm/ADT/StringRef.h"
462907617SJustin Lebar #include "llvm/ADT/StringSwitch.h"
512fefeefSArtem Belevich #include "llvm/ADT/Twine.h"
6d9bc485cSJustin Lebar #include "llvm/Support/ErrorHandling.h"
78fa28a0dSArtem Belevich #include "llvm/Support/VersionTuple.h"
862907617SJustin Lebar 
962907617SJustin Lebar namespace clang {
1062907617SJustin Lebar 
CudaVersionToString(CudaVersion V)1162907617SJustin Lebar const char *CudaVersionToString(CudaVersion V) {
1262907617SJustin Lebar   switch (V) {
1362907617SJustin Lebar   case CudaVersion::UNKNOWN:
1462907617SJustin Lebar     return "unknown";
1562907617SJustin Lebar   case CudaVersion::CUDA_70:
1662907617SJustin Lebar     return "7.0";
1762907617SJustin Lebar   case CudaVersion::CUDA_75:
1862907617SJustin Lebar     return "7.5";
1962907617SJustin Lebar   case CudaVersion::CUDA_80:
2062907617SJustin Lebar     return "8.0";
218af4e23dSArtem Belevich   case CudaVersion::CUDA_90:
228af4e23dSArtem Belevich     return "9.0";
23fbc56a90SArtem Belevich   case CudaVersion::CUDA_91:
24fbc56a90SArtem Belevich     return "9.1";
253cce3077SArtem Belevich   case CudaVersion::CUDA_92:
263cce3077SArtem Belevich     return "9.2";
2744ecb0e3SArtem Belevich   case CudaVersion::CUDA_100:
2844ecb0e3SArtem Belevich     return "10.0";
294071763bSArtem Belevich   case CudaVersion::CUDA_101:
304071763bSArtem Belevich     return "10.1";
31a9627b7eSArtem Belevich   case CudaVersion::CUDA_102:
32a9627b7eSArtem Belevich     return "10.2";
33a9627b7eSArtem Belevich   case CudaVersion::CUDA_110:
34a9627b7eSArtem Belevich     return "11.0";
352aa01cceSArtem Belevich   case CudaVersion::CUDA_111:
362aa01cceSArtem Belevich     return "11.1";
372aa01cceSArtem Belevich   case CudaVersion::CUDA_112:
382aa01cceSArtem Belevich     return "11.2";
3949d982d8SArtem Belevich   case CudaVersion::CUDA_113:
4049d982d8SArtem Belevich     return "11.3";
4149d982d8SArtem Belevich   case CudaVersion::CUDA_114:
4249d982d8SArtem Belevich     return "11.4";
437ecec3f0SCarlos Galvez   case CudaVersion::CUDA_115:
447ecec3f0SCarlos Galvez     return "11.5";
453db8e486SArtem Belevich   case CudaVersion::NEW:
463db8e486SArtem Belevich     return "";
4762907617SJustin Lebar   }
48d9bc485cSJustin Lebar   llvm_unreachable("invalid enum");
4962907617SJustin Lebar }
5062907617SJustin Lebar 
CudaStringToVersion(const llvm::Twine & S)5112fefeefSArtem Belevich CudaVersion CudaStringToVersion(const llvm::Twine &S) {
5212fefeefSArtem Belevich   return llvm::StringSwitch<CudaVersion>(S.str())
538fa28a0dSArtem Belevich       .Case("7.0", CudaVersion::CUDA_70)
548fa28a0dSArtem Belevich       .Case("7.5", CudaVersion::CUDA_75)
558fa28a0dSArtem Belevich       .Case("8.0", CudaVersion::CUDA_80)
568fa28a0dSArtem Belevich       .Case("9.0", CudaVersion::CUDA_90)
578fa28a0dSArtem Belevich       .Case("9.1", CudaVersion::CUDA_91)
588fa28a0dSArtem Belevich       .Case("9.2", CudaVersion::CUDA_92)
594071763bSArtem Belevich       .Case("10.0", CudaVersion::CUDA_100)
6012fefeefSArtem Belevich       .Case("10.1", CudaVersion::CUDA_101)
61a9627b7eSArtem Belevich       .Case("10.2", CudaVersion::CUDA_102)
62a9627b7eSArtem Belevich       .Case("11.0", CudaVersion::CUDA_110)
632aa01cceSArtem Belevich       .Case("11.1", CudaVersion::CUDA_111)
642aa01cceSArtem Belevich       .Case("11.2", CudaVersion::CUDA_112)
6549d982d8SArtem Belevich       .Case("11.3", CudaVersion::CUDA_113)
6649d982d8SArtem Belevich       .Case("11.4", CudaVersion::CUDA_114)
677ecec3f0SCarlos Galvez       .Case("11.5", CudaVersion::CUDA_115)
6812fefeefSArtem Belevich       .Default(CudaVersion::UNKNOWN);
698fa28a0dSArtem Belevich }
708fa28a0dSArtem Belevich 
711fcf9247SFangrui Song namespace {
7233386b20SArtem Belevich struct CudaArchToStringMap {
7333386b20SArtem Belevich   CudaArch arch;
7433386b20SArtem Belevich   const char *arch_name;
7533386b20SArtem Belevich   const char *virtual_arch_name;
7633386b20SArtem Belevich };
771fcf9247SFangrui Song } // namespace
7833386b20SArtem Belevich 
7933386b20SArtem Belevich #define SM2(sm, ca)                                                            \
8033386b20SArtem Belevich   { CudaArch::SM_##sm, "sm_" #sm, ca }
8133386b20SArtem Belevich #define SM(sm) SM2(sm, "compute_" #sm)
8233386b20SArtem Belevich #define GFX(gpu)                                                               \
8333386b20SArtem Belevich   { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
841fcf9247SFangrui Song static const CudaArchToStringMap arch_names[] = {
8533386b20SArtem Belevich     // clang-format off
86cbd420c5SYaxun (Sam) Liu     {CudaArch::UNUSED, "", ""},
8733386b20SArtem Belevich     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
8833386b20SArtem Belevich     SM(30), SM(32), SM(35), SM(37),  // Kepler
8933386b20SArtem Belevich     SM(50), SM(52), SM(53),          // Maxwell
9033386b20SArtem Belevich     SM(60), SM(61), SM(62),          // Pascal
9133386b20SArtem Belevich     SM(70), SM(72),                  // Volta
9233386b20SArtem Belevich     SM(75),                          // Turing
932aa01cceSArtem Belevich     SM(80), SM(86),                  // Ampere
945ad202ceSTony     GFX(600),  // gfx600
955ad202ceSTony     GFX(601),  // gfx601
965ad202ceSTony     GFX(602),  // gfx602
975ad202ceSTony     GFX(700),  // gfx700
985ad202ceSTony     GFX(701),  // gfx701
995ad202ceSTony     GFX(702),  // gfx702
1005ad202ceSTony     GFX(703),  // gfx703
1015ad202ceSTony     GFX(704),  // gfx704
1025ad202ceSTony     GFX(705),  // gfx705
1035ad202ceSTony     GFX(801),  // gfx801
1045ad202ceSTony     GFX(802),  // gfx802
1055ad202ceSTony     GFX(803),  // gfx803
1065ad202ceSTony     GFX(805),  // gfx805
1075ad202ceSTony     GFX(810),  // gfx810
1085ad202ceSTony     GFX(900),  // gfx900
1095ad202ceSTony     GFX(902),  // gfx902
1105ad202ceSTony     GFX(904),  // gfx903
1115ad202ceSTony     GFX(906),  // gfx906
1125ad202ceSTony     GFX(908),  // gfx908
1135ad202ceSTony     GFX(909),  // gfx909
114a8d9d507SStanislav Mekhanoshin     GFX(90a),  // gfx90a
1155ad202ceSTony     GFX(90c),  // gfx90c
1162e2e64dfSStanislav Mekhanoshin     GFX(940),  // gfx940
1175ad202ceSTony     GFX(1010), // gfx1010
1185ad202ceSTony     GFX(1011), // gfx1011
1195ad202ceSTony     GFX(1012), // gfx1012
120294efbbdSBrendon Cahoon     GFX(1013), // gfx1013
1215ad202ceSTony     GFX(1030), // gfx1030
1225ad202ceSTony     GFX(1031), // gfx1031
1235ad202ceSTony     GFX(1032), // gfx1032
1245ad202ceSTony     GFX(1033), // gfx1033
125464e4dc5SAakanksha Patil     GFX(1034), // gfx1034
1263453f3ddSAakanksha Patil     GFX(1035), // gfx1035
12784069581SAakanksha     GFX(1036), // gfx1036
1288bdfc73fSJoe Nash     GFX(1100), // gfx1100
1298bdfc73fSJoe Nash     GFX(1101), // gfx1101
1308bdfc73fSJoe Nash     GFX(1102), // gfx1102
1318bdfc73fSJoe Nash     GFX(1103), // gfx1103
132a6786cddSYaxun (Sam) Liu     {CudaArch::Generic, "generic", ""},
13333386b20SArtem Belevich     // clang-format on
13433386b20SArtem Belevich };
13533386b20SArtem Belevich #undef SM
13633386b20SArtem Belevich #undef SM2
13733386b20SArtem Belevich #undef GFX
13833386b20SArtem Belevich 
CudaArchToString(CudaArch A)13962907617SJustin Lebar const char *CudaArchToString(CudaArch A) {
14033386b20SArtem Belevich   auto result = std::find_if(
14133386b20SArtem Belevich       std::begin(arch_names), std::end(arch_names),
14233386b20SArtem Belevich       [A](const CudaArchToStringMap &map) { return A == map.arch; });
14333386b20SArtem Belevich   if (result == std::end(arch_names))
14462907617SJustin Lebar     return "unknown";
14533386b20SArtem Belevich   return result->arch_name;
14662907617SJustin Lebar }
14733386b20SArtem Belevich 
CudaArchToVirtualArchString(CudaArch A)14833386b20SArtem Belevich const char *CudaArchToVirtualArchString(CudaArch A) {
14933386b20SArtem Belevich   auto result = std::find_if(
15033386b20SArtem Belevich       std::begin(arch_names), std::end(arch_names),
15133386b20SArtem Belevich       [A](const CudaArchToStringMap &map) { return A == map.arch; });
15233386b20SArtem Belevich   if (result == std::end(arch_names))
15333386b20SArtem Belevich     return "unknown";
15433386b20SArtem Belevich   return result->virtual_arch_name;
15562907617SJustin Lebar }
15662907617SJustin Lebar 
StringToCudaArch(llvm::StringRef S)15762907617SJustin Lebar CudaArch StringToCudaArch(llvm::StringRef S) {
15833386b20SArtem Belevich   auto result = std::find_if(
15933386b20SArtem Belevich       std::begin(arch_names), std::end(arch_names),
16033386b20SArtem Belevich       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
16133386b20SArtem Belevich   if (result == std::end(arch_names))
16233386b20SArtem Belevich     return CudaArch::UNKNOWN;
16333386b20SArtem Belevich   return result->arch;
16462907617SJustin Lebar }
16562907617SJustin Lebar 
MinVersionForCudaArch(CudaArch A)16662907617SJustin Lebar CudaVersion MinVersionForCudaArch(CudaArch A) {
16733386b20SArtem Belevich   if (A == CudaArch::UNKNOWN)
16862907617SJustin Lebar     return CudaVersion::UNKNOWN;
16933386b20SArtem Belevich 
17033386b20SArtem Belevich   // AMD GPUs do not depend on CUDA versions.
17133386b20SArtem Belevich   if (IsAMDGpuArch(A))
17233386b20SArtem Belevich     return CudaVersion::CUDA_70;
17333386b20SArtem Belevich 
17433386b20SArtem Belevich   switch (A) {
17562907617SJustin Lebar   case CudaArch::SM_20:
17662907617SJustin Lebar   case CudaArch::SM_21:
17762907617SJustin Lebar   case CudaArch::SM_30:
17862907617SJustin Lebar   case CudaArch::SM_32:
17962907617SJustin Lebar   case CudaArch::SM_35:
18062907617SJustin Lebar   case CudaArch::SM_37:
18162907617SJustin Lebar   case CudaArch::SM_50:
18262907617SJustin Lebar   case CudaArch::SM_52:
18362907617SJustin Lebar   case CudaArch::SM_53:
18462907617SJustin Lebar     return CudaVersion::CUDA_70;
18562907617SJustin Lebar   case CudaArch::SM_60:
18662907617SJustin Lebar   case CudaArch::SM_61:
18762907617SJustin Lebar   case CudaArch::SM_62:
18862907617SJustin Lebar     return CudaVersion::CUDA_80;
1898af4e23dSArtem Belevich   case CudaArch::SM_70:
1908af4e23dSArtem Belevich     return CudaVersion::CUDA_90;
191fbc56a90SArtem Belevich   case CudaArch::SM_72:
192fbc56a90SArtem Belevich     return CudaVersion::CUDA_91;
19344ecb0e3SArtem Belevich   case CudaArch::SM_75:
19444ecb0e3SArtem Belevich     return CudaVersion::CUDA_100;
195a9627b7eSArtem Belevich   case CudaArch::SM_80:
196a9627b7eSArtem Belevich     return CudaVersion::CUDA_110;
1972aa01cceSArtem Belevich   case CudaArch::SM_86:
1982aa01cceSArtem Belevich     return CudaVersion::CUDA_111;
19933386b20SArtem Belevich   default:
200d9bc485cSJustin Lebar     llvm_unreachable("invalid enum");
20162907617SJustin Lebar   }
20233386b20SArtem Belevich }
20362907617SJustin Lebar 
MaxVersionForCudaArch(CudaArch A)204066494d8SJustin Lebar CudaVersion MaxVersionForCudaArch(CudaArch A) {
20533386b20SArtem Belevich   // AMD GPUs do not depend on CUDA versions.
20633386b20SArtem Belevich   if (IsAMDGpuArch(A))
2073db8e486SArtem Belevich     return CudaVersion::NEW;
20833386b20SArtem Belevich 
209066494d8SJustin Lebar   switch (A) {
210066494d8SJustin Lebar   case CudaArch::UNKNOWN:
211066494d8SJustin Lebar     return CudaVersion::UNKNOWN;
212066494d8SJustin Lebar   case CudaArch::SM_20:
213066494d8SJustin Lebar   case CudaArch::SM_21:
214066494d8SJustin Lebar     return CudaVersion::CUDA_80;
21549d982d8SArtem Belevich   case CudaArch::SM_30:
21649d982d8SArtem Belevich     return CudaVersion::CUDA_110;
217066494d8SJustin Lebar   default:
2183db8e486SArtem Belevich     return CudaVersion::NEW;
219066494d8SJustin Lebar   }
220066494d8SJustin Lebar }
221066494d8SJustin Lebar 
ToCudaVersion(llvm::VersionTuple Version)222b952d799SMichael Liao CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
223*06decd0bSKazu Hirata   int IVer = Version.getMajor() * 10 + Version.getMinor().value_or(0);
2248fa28a0dSArtem Belevich   switch(IVer) {
2258fa28a0dSArtem Belevich   case 70:
2268fa28a0dSArtem Belevich     return CudaVersion::CUDA_70;
2278fa28a0dSArtem Belevich   case 75:
2288fa28a0dSArtem Belevich     return CudaVersion::CUDA_75;
2298fa28a0dSArtem Belevich   case 80:
2308fa28a0dSArtem Belevich     return CudaVersion::CUDA_80;
2318fa28a0dSArtem Belevich   case 90:
2328fa28a0dSArtem Belevich     return CudaVersion::CUDA_90;
2338fa28a0dSArtem Belevich   case 91:
2348fa28a0dSArtem Belevich     return CudaVersion::CUDA_91;
2358fa28a0dSArtem Belevich   case 92:
2368fa28a0dSArtem Belevich     return CudaVersion::CUDA_92;
2378fa28a0dSArtem Belevich   case 100:
2388fa28a0dSArtem Belevich     return CudaVersion::CUDA_100;
2394071763bSArtem Belevich   case 101:
2404071763bSArtem Belevich     return CudaVersion::CUDA_101;
2418c635ba4SArtem Belevich   case 102:
2428c635ba4SArtem Belevich     return CudaVersion::CUDA_102;
2438c635ba4SArtem Belevich   case 110:
2448c635ba4SArtem Belevich     return CudaVersion::CUDA_110;
2452aa01cceSArtem Belevich   case 111:
2462aa01cceSArtem Belevich     return CudaVersion::CUDA_111;
2472aa01cceSArtem Belevich   case 112:
2482aa01cceSArtem Belevich     return CudaVersion::CUDA_112;
24949d982d8SArtem Belevich   case 113:
25049d982d8SArtem Belevich     return CudaVersion::CUDA_113;
25149d982d8SArtem Belevich   case 114:
25249d982d8SArtem Belevich     return CudaVersion::CUDA_114;
2537ecec3f0SCarlos Galvez   case 115:
2547ecec3f0SCarlos Galvez     return CudaVersion::CUDA_115;
2558fa28a0dSArtem Belevich   default:
2568fa28a0dSArtem Belevich     return CudaVersion::UNKNOWN;
2578fa28a0dSArtem Belevich   }
2588fa28a0dSArtem Belevich }
2598fa28a0dSArtem Belevich 
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)2608fa28a0dSArtem Belevich bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
2618fa28a0dSArtem Belevich   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2628fa28a0dSArtem Belevich }
2638fa28a0dSArtem Belevich 
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)2648fa28a0dSArtem Belevich bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2658fa28a0dSArtem Belevich   switch (Feature) {
2668fa28a0dSArtem Belevich   case CudaFeature::CUDA_USES_NEW_LAUNCH:
2678fa28a0dSArtem Belevich     return Version >= CudaVersion::CUDA_92;
2684071763bSArtem Belevich   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2694071763bSArtem Belevich     return Version >= CudaVersion::CUDA_101;
2708fa28a0dSArtem Belevich   }
2718fa28a0dSArtem Belevich   llvm_unreachable("Unknown CUDA feature.");
2728fa28a0dSArtem Belevich }
27362907617SJustin Lebar } // namespace clang
274