xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Cuda.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric #include "clang/Basic/Cuda.h"
20b57cec5SDimitry Andric 
30b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
413138422SDimitry Andric #include "llvm/ADT/Twine.h"
50b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
60b57cec5SDimitry Andric #include "llvm/Support/VersionTuple.h"
70b57cec5SDimitry Andric 
80b57cec5SDimitry Andric namespace clang {
90b57cec5SDimitry Andric 
10bdd1243dSDimitry Andric struct CudaVersionMapEntry {
11bdd1243dSDimitry Andric   const char *Name;
12bdd1243dSDimitry Andric   CudaVersion Version;
13bdd1243dSDimitry Andric   llvm::VersionTuple TVersion;
14bdd1243dSDimitry Andric };
15bdd1243dSDimitry Andric #define CUDA_ENTRY(major, minor)                                               \
16bdd1243dSDimitry Andric   {                                                                            \
17bdd1243dSDimitry Andric #major "." #minor, CudaVersion::CUDA_##major##minor,                       \
18bdd1243dSDimitry Andric         llvm::VersionTuple(major, minor)                                       \
190b57cec5SDimitry Andric   }
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric static const CudaVersionMapEntry CudaNameVersionMap[] = {
22bdd1243dSDimitry Andric     CUDA_ENTRY(7, 0),
23bdd1243dSDimitry Andric     CUDA_ENTRY(7, 5),
24bdd1243dSDimitry Andric     CUDA_ENTRY(8, 0),
25bdd1243dSDimitry Andric     CUDA_ENTRY(9, 0),
26bdd1243dSDimitry Andric     CUDA_ENTRY(9, 1),
27bdd1243dSDimitry Andric     CUDA_ENTRY(9, 2),
28bdd1243dSDimitry Andric     CUDA_ENTRY(10, 0),
29bdd1243dSDimitry Andric     CUDA_ENTRY(10, 1),
30bdd1243dSDimitry Andric     CUDA_ENTRY(10, 2),
31bdd1243dSDimitry Andric     CUDA_ENTRY(11, 0),
32bdd1243dSDimitry Andric     CUDA_ENTRY(11, 1),
33bdd1243dSDimitry Andric     CUDA_ENTRY(11, 2),
34bdd1243dSDimitry Andric     CUDA_ENTRY(11, 3),
35bdd1243dSDimitry Andric     CUDA_ENTRY(11, 4),
36bdd1243dSDimitry Andric     CUDA_ENTRY(11, 5),
37bdd1243dSDimitry Andric     CUDA_ENTRY(11, 6),
38bdd1243dSDimitry Andric     CUDA_ENTRY(11, 7),
39bdd1243dSDimitry Andric     CUDA_ENTRY(11, 8),
40*06c3fb27SDimitry Andric     CUDA_ENTRY(12, 0),
41*06c3fb27SDimitry Andric     CUDA_ENTRY(12, 1),
42bdd1243dSDimitry Andric     {"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
43bdd1243dSDimitry Andric     {"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
44bdd1243dSDimitry Andric };
45bdd1243dSDimitry Andric #undef CUDA_ENTRY
46bdd1243dSDimitry Andric 
47bdd1243dSDimitry Andric const char *CudaVersionToString(CudaVersion V) {
48bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
49bdd1243dSDimitry Andric     if (I->Version == V)
50bdd1243dSDimitry Andric       return I->Name;
51bdd1243dSDimitry Andric 
52bdd1243dSDimitry Andric   return CudaVersionToString(CudaVersion::UNKNOWN);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
5513138422SDimitry Andric CudaVersion CudaStringToVersion(const llvm::Twine &S) {
56bdd1243dSDimitry Andric   std::string VS = S.str();
57bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
58bdd1243dSDimitry Andric     if (I->Name == VS)
59bdd1243dSDimitry Andric       return I->Version;
60bdd1243dSDimitry Andric   return CudaVersion::UNKNOWN;
61bdd1243dSDimitry Andric }
62bdd1243dSDimitry Andric 
63bdd1243dSDimitry Andric CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
64bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
65bdd1243dSDimitry Andric     if (I->TVersion == Version)
66bdd1243dSDimitry Andric       return I->Version;
67bdd1243dSDimitry Andric   return CudaVersion::UNKNOWN;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
70fe6060f1SDimitry Andric namespace {
715ffd83dbSDimitry Andric struct CudaArchToStringMap {
725ffd83dbSDimitry Andric   CudaArch arch;
735ffd83dbSDimitry Andric   const char *arch_name;
745ffd83dbSDimitry Andric   const char *virtual_arch_name;
755ffd83dbSDimitry Andric };
76fe6060f1SDimitry Andric } // namespace
775ffd83dbSDimitry Andric 
785ffd83dbSDimitry Andric #define SM2(sm, ca)                                                            \
795ffd83dbSDimitry Andric   { CudaArch::SM_##sm, "sm_" #sm, ca }
805ffd83dbSDimitry Andric #define SM(sm) SM2(sm, "compute_" #sm)
815ffd83dbSDimitry Andric #define GFX(gpu)                                                               \
825ffd83dbSDimitry Andric   { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
83fe6060f1SDimitry Andric static const CudaArchToStringMap arch_names[] = {
845ffd83dbSDimitry Andric     // clang-format off
85e8d8bef9SDimitry Andric     {CudaArch::UNUSED, "", ""},
865ffd83dbSDimitry Andric     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
875ffd83dbSDimitry Andric     SM(30), SM(32), SM(35), SM(37),  // Kepler
885ffd83dbSDimitry Andric     SM(50), SM(52), SM(53),          // Maxwell
895ffd83dbSDimitry Andric     SM(60), SM(61), SM(62),          // Pascal
905ffd83dbSDimitry Andric     SM(70), SM(72),                  // Volta
915ffd83dbSDimitry Andric     SM(75),                          // Turing
92fe6060f1SDimitry Andric     SM(80), SM(86),                  // Ampere
93bdd1243dSDimitry Andric     SM(87),                          // Jetson/Drive AGX Orin
94bdd1243dSDimitry Andric     SM(89),                          // Ada Lovelace
95bdd1243dSDimitry Andric     SM(90),                          // Hopper
96e8d8bef9SDimitry Andric     GFX(600),  // gfx600
97e8d8bef9SDimitry Andric     GFX(601),  // gfx601
98e8d8bef9SDimitry Andric     GFX(602),  // gfx602
99e8d8bef9SDimitry Andric     GFX(700),  // gfx700
100e8d8bef9SDimitry Andric     GFX(701),  // gfx701
101e8d8bef9SDimitry Andric     GFX(702),  // gfx702
102e8d8bef9SDimitry Andric     GFX(703),  // gfx703
103e8d8bef9SDimitry Andric     GFX(704),  // gfx704
104e8d8bef9SDimitry Andric     GFX(705),  // gfx705
105e8d8bef9SDimitry Andric     GFX(801),  // gfx801
106e8d8bef9SDimitry Andric     GFX(802),  // gfx802
107e8d8bef9SDimitry Andric     GFX(803),  // gfx803
108e8d8bef9SDimitry Andric     GFX(805),  // gfx805
109e8d8bef9SDimitry Andric     GFX(810),  // gfx810
110e8d8bef9SDimitry Andric     GFX(900),  // gfx900
111e8d8bef9SDimitry Andric     GFX(902),  // gfx902
112e8d8bef9SDimitry Andric     GFX(904),  // gfx903
113e8d8bef9SDimitry Andric     GFX(906),  // gfx906
114e8d8bef9SDimitry Andric     GFX(908),  // gfx908
115e8d8bef9SDimitry Andric     GFX(909),  // gfx909
116fe6060f1SDimitry Andric     GFX(90a),  // gfx90a
117e8d8bef9SDimitry Andric     GFX(90c),  // gfx90c
11881ad6265SDimitry Andric     GFX(940),  // gfx940
119*06c3fb27SDimitry Andric     GFX(941),  // gfx941
120*06c3fb27SDimitry Andric     GFX(942),  // gfx942
121e8d8bef9SDimitry Andric     GFX(1010), // gfx1010
122e8d8bef9SDimitry Andric     GFX(1011), // gfx1011
123e8d8bef9SDimitry Andric     GFX(1012), // gfx1012
124fe6060f1SDimitry Andric     GFX(1013), // gfx1013
125e8d8bef9SDimitry Andric     GFX(1030), // gfx1030
126e8d8bef9SDimitry Andric     GFX(1031), // gfx1031
127e8d8bef9SDimitry Andric     GFX(1032), // gfx1032
128e8d8bef9SDimitry Andric     GFX(1033), // gfx1033
129fe6060f1SDimitry Andric     GFX(1034), // gfx1034
130fe6060f1SDimitry Andric     GFX(1035), // gfx1035
13181ad6265SDimitry Andric     GFX(1036), // gfx1036
13281ad6265SDimitry Andric     GFX(1100), // gfx1100
13381ad6265SDimitry Andric     GFX(1101), // gfx1101
13481ad6265SDimitry Andric     GFX(1102), // gfx1102
13581ad6265SDimitry Andric     GFX(1103), // gfx1103
136*06c3fb27SDimitry Andric     GFX(1150), // gfx1150
137*06c3fb27SDimitry Andric     GFX(1151), // gfx1151
1380eae32dcSDimitry Andric     {CudaArch::Generic, "generic", ""},
1395ffd83dbSDimitry Andric     // clang-format on
1405ffd83dbSDimitry Andric };
1415ffd83dbSDimitry Andric #undef SM
1425ffd83dbSDimitry Andric #undef SM2
1435ffd83dbSDimitry Andric #undef GFX
1445ffd83dbSDimitry Andric 
1450b57cec5SDimitry Andric const char *CudaArchToString(CudaArch A) {
1465ffd83dbSDimitry Andric   auto result = std::find_if(
1475ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1485ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
1495ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1500b57cec5SDimitry Andric     return "unknown";
1515ffd83dbSDimitry Andric   return result->arch_name;
1520b57cec5SDimitry Andric }
1535ffd83dbSDimitry Andric 
1545ffd83dbSDimitry Andric const char *CudaArchToVirtualArchString(CudaArch A) {
1555ffd83dbSDimitry Andric   auto result = std::find_if(
1565ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1575ffd83dbSDimitry Andric       [A](const CudaArchToStringMap &map) { return A == map.arch; });
1585ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1595ffd83dbSDimitry Andric     return "unknown";
1605ffd83dbSDimitry Andric   return result->virtual_arch_name;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric CudaArch StringToCudaArch(llvm::StringRef S) {
1645ffd83dbSDimitry Andric   auto result = std::find_if(
1655ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
1665ffd83dbSDimitry Andric       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
1675ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1685ffd83dbSDimitry Andric     return CudaArch::UNKNOWN;
1695ffd83dbSDimitry Andric   return result->arch;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric CudaVersion MinVersionForCudaArch(CudaArch A) {
1735ffd83dbSDimitry Andric   if (A == CudaArch::UNKNOWN)
1740b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1755ffd83dbSDimitry Andric 
1765ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
1775ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
1785ffd83dbSDimitry Andric     return CudaVersion::CUDA_70;
1795ffd83dbSDimitry Andric 
1805ffd83dbSDimitry Andric   switch (A) {
1810b57cec5SDimitry Andric   case CudaArch::SM_20:
1820b57cec5SDimitry Andric   case CudaArch::SM_21:
1830b57cec5SDimitry Andric   case CudaArch::SM_30:
1840b57cec5SDimitry Andric   case CudaArch::SM_32:
1850b57cec5SDimitry Andric   case CudaArch::SM_35:
1860b57cec5SDimitry Andric   case CudaArch::SM_37:
1870b57cec5SDimitry Andric   case CudaArch::SM_50:
1880b57cec5SDimitry Andric   case CudaArch::SM_52:
1890b57cec5SDimitry Andric   case CudaArch::SM_53:
1900b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
1910b57cec5SDimitry Andric   case CudaArch::SM_60:
1920b57cec5SDimitry Andric   case CudaArch::SM_61:
1930b57cec5SDimitry Andric   case CudaArch::SM_62:
1940b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
1950b57cec5SDimitry Andric   case CudaArch::SM_70:
1960b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
1970b57cec5SDimitry Andric   case CudaArch::SM_72:
1980b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
1990b57cec5SDimitry Andric   case CudaArch::SM_75:
2000b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
2015ffd83dbSDimitry Andric   case CudaArch::SM_80:
2025ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
203fe6060f1SDimitry Andric   case CudaArch::SM_86:
204fe6060f1SDimitry Andric     return CudaVersion::CUDA_111;
205bdd1243dSDimitry Andric   case CudaArch::SM_87:
206bdd1243dSDimitry Andric     return CudaVersion::CUDA_114;
207bdd1243dSDimitry Andric   case CudaArch::SM_89:
208bdd1243dSDimitry Andric   case CudaArch::SM_90:
209bdd1243dSDimitry Andric     return CudaVersion::CUDA_118;
2105ffd83dbSDimitry Andric   default:
2110b57cec5SDimitry Andric     llvm_unreachable("invalid enum");
2120b57cec5SDimitry Andric   }
2135ffd83dbSDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric CudaVersion MaxVersionForCudaArch(CudaArch A) {
2165ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
2175ffd83dbSDimitry Andric   if (IsAMDGpuArch(A))
218349cc55cSDimitry Andric     return CudaVersion::NEW;
2195ffd83dbSDimitry Andric 
2200b57cec5SDimitry Andric   switch (A) {
2210b57cec5SDimitry Andric   case CudaArch::UNKNOWN:
2220b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
2230b57cec5SDimitry Andric   case CudaArch::SM_20:
2240b57cec5SDimitry Andric   case CudaArch::SM_21:
2250b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
226349cc55cSDimitry Andric   case CudaArch::SM_30:
227*06c3fb27SDimitry Andric   case CudaArch::SM_32:
228*06c3fb27SDimitry Andric     return CudaVersion::CUDA_102;
229*06c3fb27SDimitry Andric   case CudaArch::SM_35:
230*06c3fb27SDimitry Andric   case CudaArch::SM_37:
231*06c3fb27SDimitry Andric     return CudaVersion::CUDA_118;
2320b57cec5SDimitry Andric   default:
233349cc55cSDimitry Andric     return CudaVersion::NEW;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
2380b57cec5SDimitry Andric   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2420b57cec5SDimitry Andric   switch (Feature) {
2430b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_NEW_LAUNCH:
2440b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_92;
2450b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2460b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_101;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric   llvm_unreachable("Unknown CUDA feature.");
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric } // namespace clang
251