xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Cuda.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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),
4006c3fb27SDimitry Andric     CUDA_ENTRY(12, 0),
4106c3fb27SDimitry Andric     CUDA_ENTRY(12, 1),
425f757f3fSDimitry Andric     CUDA_ENTRY(12, 2),
435f757f3fSDimitry Andric     CUDA_ENTRY(12, 3),
44*0fca6ea1SDimitry Andric     CUDA_ENTRY(12, 4),
45*0fca6ea1SDimitry Andric     CUDA_ENTRY(12, 5),
46bdd1243dSDimitry Andric     {"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
47bdd1243dSDimitry Andric     {"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
48bdd1243dSDimitry Andric };
49bdd1243dSDimitry Andric #undef CUDA_ENTRY
50bdd1243dSDimitry Andric 
CudaVersionToString(CudaVersion V)51bdd1243dSDimitry Andric const char *CudaVersionToString(CudaVersion V) {
52bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
53bdd1243dSDimitry Andric     if (I->Version == V)
54bdd1243dSDimitry Andric       return I->Name;
55bdd1243dSDimitry Andric 
56bdd1243dSDimitry Andric   return CudaVersionToString(CudaVersion::UNKNOWN);
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
CudaStringToVersion(const llvm::Twine & S)5913138422SDimitry Andric CudaVersion CudaStringToVersion(const llvm::Twine &S) {
60bdd1243dSDimitry Andric   std::string VS = S.str();
61bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
62bdd1243dSDimitry Andric     if (I->Name == VS)
63bdd1243dSDimitry Andric       return I->Version;
64bdd1243dSDimitry Andric   return CudaVersion::UNKNOWN;
65bdd1243dSDimitry Andric }
66bdd1243dSDimitry Andric 
ToCudaVersion(llvm::VersionTuple Version)67bdd1243dSDimitry Andric CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
68bdd1243dSDimitry Andric   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
69bdd1243dSDimitry Andric     if (I->TVersion == Version)
70bdd1243dSDimitry Andric       return I->Version;
71bdd1243dSDimitry Andric   return CudaVersion::UNKNOWN;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
74fe6060f1SDimitry Andric namespace {
75*0fca6ea1SDimitry Andric struct OffloadArchToStringMap {
76*0fca6ea1SDimitry Andric   OffloadArch arch;
775ffd83dbSDimitry Andric   const char *arch_name;
785ffd83dbSDimitry Andric   const char *virtual_arch_name;
795ffd83dbSDimitry Andric };
80fe6060f1SDimitry Andric } // namespace
815ffd83dbSDimitry Andric 
82*0fca6ea1SDimitry Andric #define SM2(sm, ca) {OffloadArch::SM_##sm, "sm_" #sm, ca}
835ffd83dbSDimitry Andric #define SM(sm) SM2(sm, "compute_" #sm)
84*0fca6ea1SDimitry Andric #define GFX(gpu) {OffloadArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn"}
85*0fca6ea1SDimitry Andric static const OffloadArchToStringMap arch_names[] = {
865ffd83dbSDimitry Andric     // clang-format off
87*0fca6ea1SDimitry Andric     {OffloadArch::UNUSED, "", ""},
885ffd83dbSDimitry Andric     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
89*0fca6ea1SDimitry Andric     SM(30), {OffloadArch::SM_32_, "sm_32", "compute_32"}, SM(35), SM(37),  // Kepler
905ffd83dbSDimitry Andric     SM(50), SM(52), SM(53),          // Maxwell
915ffd83dbSDimitry Andric     SM(60), SM(61), SM(62),          // Pascal
925ffd83dbSDimitry Andric     SM(70), SM(72),                  // Volta
935ffd83dbSDimitry Andric     SM(75),                          // Turing
94fe6060f1SDimitry Andric     SM(80), SM(86),                  // Ampere
95bdd1243dSDimitry Andric     SM(87),                          // Jetson/Drive AGX Orin
96bdd1243dSDimitry Andric     SM(89),                          // Ada Lovelace
97bdd1243dSDimitry Andric     SM(90),                          // Hopper
985f757f3fSDimitry Andric     SM(90a),                         // Hopper
99e8d8bef9SDimitry Andric     GFX(600),  // gfx600
100e8d8bef9SDimitry Andric     GFX(601),  // gfx601
101e8d8bef9SDimitry Andric     GFX(602),  // gfx602
102e8d8bef9SDimitry Andric     GFX(700),  // gfx700
103e8d8bef9SDimitry Andric     GFX(701),  // gfx701
104e8d8bef9SDimitry Andric     GFX(702),  // gfx702
105e8d8bef9SDimitry Andric     GFX(703),  // gfx703
106e8d8bef9SDimitry Andric     GFX(704),  // gfx704
107e8d8bef9SDimitry Andric     GFX(705),  // gfx705
108e8d8bef9SDimitry Andric     GFX(801),  // gfx801
109e8d8bef9SDimitry Andric     GFX(802),  // gfx802
110e8d8bef9SDimitry Andric     GFX(803),  // gfx803
111e8d8bef9SDimitry Andric     GFX(805),  // gfx805
112e8d8bef9SDimitry Andric     GFX(810),  // gfx810
113*0fca6ea1SDimitry Andric     {OffloadArch::GFX9_GENERIC, "gfx9-generic", "compute_amdgcn"},
114e8d8bef9SDimitry Andric     GFX(900),  // gfx900
115e8d8bef9SDimitry Andric     GFX(902),  // gfx902
116e8d8bef9SDimitry Andric     GFX(904),  // gfx903
117e8d8bef9SDimitry Andric     GFX(906),  // gfx906
118e8d8bef9SDimitry Andric     GFX(908),  // gfx908
119e8d8bef9SDimitry Andric     GFX(909),  // gfx909
120fe6060f1SDimitry Andric     GFX(90a),  // gfx90a
121e8d8bef9SDimitry Andric     GFX(90c),  // gfx90c
12281ad6265SDimitry Andric     GFX(940),  // gfx940
12306c3fb27SDimitry Andric     GFX(941),  // gfx941
12406c3fb27SDimitry Andric     GFX(942),  // gfx942
125*0fca6ea1SDimitry Andric     {OffloadArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"},
126e8d8bef9SDimitry Andric     GFX(1010), // gfx1010
127e8d8bef9SDimitry Andric     GFX(1011), // gfx1011
128e8d8bef9SDimitry Andric     GFX(1012), // gfx1012
129fe6060f1SDimitry Andric     GFX(1013), // gfx1013
130*0fca6ea1SDimitry Andric     {OffloadArch::GFX10_3_GENERIC, "gfx10-3-generic", "compute_amdgcn"},
131e8d8bef9SDimitry Andric     GFX(1030), // gfx1030
132e8d8bef9SDimitry Andric     GFX(1031), // gfx1031
133e8d8bef9SDimitry Andric     GFX(1032), // gfx1032
134e8d8bef9SDimitry Andric     GFX(1033), // gfx1033
135fe6060f1SDimitry Andric     GFX(1034), // gfx1034
136fe6060f1SDimitry Andric     GFX(1035), // gfx1035
13781ad6265SDimitry Andric     GFX(1036), // gfx1036
138*0fca6ea1SDimitry Andric     {OffloadArch::GFX11_GENERIC, "gfx11-generic", "compute_amdgcn"},
13981ad6265SDimitry Andric     GFX(1100), // gfx1100
14081ad6265SDimitry Andric     GFX(1101), // gfx1101
14181ad6265SDimitry Andric     GFX(1102), // gfx1102
14281ad6265SDimitry Andric     GFX(1103), // gfx1103
14306c3fb27SDimitry Andric     GFX(1150), // gfx1150
14406c3fb27SDimitry Andric     GFX(1151), // gfx1151
145*0fca6ea1SDimitry Andric     GFX(1152), // gfx1152
146*0fca6ea1SDimitry Andric     {OffloadArch::GFX12_GENERIC, "gfx12-generic", "compute_amdgcn"},
1475f757f3fSDimitry Andric     GFX(1200), // gfx1200
1485f757f3fSDimitry Andric     GFX(1201), // gfx1201
149*0fca6ea1SDimitry Andric     {OffloadArch::AMDGCNSPIRV, "amdgcnspirv", "compute_amdgcn"},
150*0fca6ea1SDimitry Andric     {OffloadArch::Generic, "generic", ""},
1515ffd83dbSDimitry Andric     // clang-format on
1525ffd83dbSDimitry Andric };
1535ffd83dbSDimitry Andric #undef SM
1545ffd83dbSDimitry Andric #undef SM2
1555ffd83dbSDimitry Andric #undef GFX
1565ffd83dbSDimitry Andric 
OffloadArchToString(OffloadArch A)157*0fca6ea1SDimitry Andric const char *OffloadArchToString(OffloadArch A) {
1585ffd83dbSDimitry Andric   auto result = std::find_if(
1595ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
160*0fca6ea1SDimitry Andric       [A](const OffloadArchToStringMap &map) { return A == map.arch; });
1615ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1620b57cec5SDimitry Andric     return "unknown";
1635ffd83dbSDimitry Andric   return result->arch_name;
1640b57cec5SDimitry Andric }
1655ffd83dbSDimitry Andric 
OffloadArchToVirtualArchString(OffloadArch A)166*0fca6ea1SDimitry Andric const char *OffloadArchToVirtualArchString(OffloadArch A) {
1675ffd83dbSDimitry Andric   auto result = std::find_if(
1685ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
169*0fca6ea1SDimitry Andric       [A](const OffloadArchToStringMap &map) { return A == map.arch; });
1705ffd83dbSDimitry Andric   if (result == std::end(arch_names))
1715ffd83dbSDimitry Andric     return "unknown";
1725ffd83dbSDimitry Andric   return result->virtual_arch_name;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
StringToOffloadArch(llvm::StringRef S)175*0fca6ea1SDimitry Andric OffloadArch StringToOffloadArch(llvm::StringRef S) {
1765ffd83dbSDimitry Andric   auto result = std::find_if(
1775ffd83dbSDimitry Andric       std::begin(arch_names), std::end(arch_names),
178*0fca6ea1SDimitry Andric       [S](const OffloadArchToStringMap &map) { return S == map.arch_name; });
1795ffd83dbSDimitry Andric   if (result == std::end(arch_names))
180*0fca6ea1SDimitry Andric     return OffloadArch::UNKNOWN;
1815ffd83dbSDimitry Andric   return result->arch;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
MinVersionForOffloadArch(OffloadArch A)184*0fca6ea1SDimitry Andric CudaVersion MinVersionForOffloadArch(OffloadArch A) {
185*0fca6ea1SDimitry Andric   if (A == OffloadArch::UNKNOWN)
1860b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
1875ffd83dbSDimitry Andric 
1885ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
189*0fca6ea1SDimitry Andric   if (IsAMDOffloadArch(A))
1905ffd83dbSDimitry Andric     return CudaVersion::CUDA_70;
1915ffd83dbSDimitry Andric 
1925ffd83dbSDimitry Andric   switch (A) {
193*0fca6ea1SDimitry Andric   case OffloadArch::SM_20:
194*0fca6ea1SDimitry Andric   case OffloadArch::SM_21:
195*0fca6ea1SDimitry Andric   case OffloadArch::SM_30:
196*0fca6ea1SDimitry Andric   case OffloadArch::SM_32_:
197*0fca6ea1SDimitry Andric   case OffloadArch::SM_35:
198*0fca6ea1SDimitry Andric   case OffloadArch::SM_37:
199*0fca6ea1SDimitry Andric   case OffloadArch::SM_50:
200*0fca6ea1SDimitry Andric   case OffloadArch::SM_52:
201*0fca6ea1SDimitry Andric   case OffloadArch::SM_53:
2020b57cec5SDimitry Andric     return CudaVersion::CUDA_70;
203*0fca6ea1SDimitry Andric   case OffloadArch::SM_60:
204*0fca6ea1SDimitry Andric   case OffloadArch::SM_61:
205*0fca6ea1SDimitry Andric   case OffloadArch::SM_62:
2060b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
207*0fca6ea1SDimitry Andric   case OffloadArch::SM_70:
2080b57cec5SDimitry Andric     return CudaVersion::CUDA_90;
209*0fca6ea1SDimitry Andric   case OffloadArch::SM_72:
2100b57cec5SDimitry Andric     return CudaVersion::CUDA_91;
211*0fca6ea1SDimitry Andric   case OffloadArch::SM_75:
2120b57cec5SDimitry Andric     return CudaVersion::CUDA_100;
213*0fca6ea1SDimitry Andric   case OffloadArch::SM_80:
2145ffd83dbSDimitry Andric     return CudaVersion::CUDA_110;
215*0fca6ea1SDimitry Andric   case OffloadArch::SM_86:
216fe6060f1SDimitry Andric     return CudaVersion::CUDA_111;
217*0fca6ea1SDimitry Andric   case OffloadArch::SM_87:
218bdd1243dSDimitry Andric     return CudaVersion::CUDA_114;
219*0fca6ea1SDimitry Andric   case OffloadArch::SM_89:
220*0fca6ea1SDimitry Andric   case OffloadArch::SM_90:
221bdd1243dSDimitry Andric     return CudaVersion::CUDA_118;
222*0fca6ea1SDimitry Andric   case OffloadArch::SM_90a:
2235f757f3fSDimitry Andric     return CudaVersion::CUDA_120;
2245ffd83dbSDimitry Andric   default:
2250b57cec5SDimitry Andric     llvm_unreachable("invalid enum");
2260b57cec5SDimitry Andric   }
2275ffd83dbSDimitry Andric }
2280b57cec5SDimitry Andric 
MaxVersionForOffloadArch(OffloadArch A)229*0fca6ea1SDimitry Andric CudaVersion MaxVersionForOffloadArch(OffloadArch A) {
2305ffd83dbSDimitry Andric   // AMD GPUs do not depend on CUDA versions.
231*0fca6ea1SDimitry Andric   if (IsAMDOffloadArch(A))
232349cc55cSDimitry Andric     return CudaVersion::NEW;
2335ffd83dbSDimitry Andric 
2340b57cec5SDimitry Andric   switch (A) {
235*0fca6ea1SDimitry Andric   case OffloadArch::UNKNOWN:
2360b57cec5SDimitry Andric     return CudaVersion::UNKNOWN;
237*0fca6ea1SDimitry Andric   case OffloadArch::SM_20:
238*0fca6ea1SDimitry Andric   case OffloadArch::SM_21:
2390b57cec5SDimitry Andric     return CudaVersion::CUDA_80;
240*0fca6ea1SDimitry Andric   case OffloadArch::SM_30:
241*0fca6ea1SDimitry Andric   case OffloadArch::SM_32_:
24206c3fb27SDimitry Andric     return CudaVersion::CUDA_102;
243*0fca6ea1SDimitry Andric   case OffloadArch::SM_35:
244*0fca6ea1SDimitry Andric   case OffloadArch::SM_37:
24506c3fb27SDimitry Andric     return CudaVersion::CUDA_118;
2460b57cec5SDimitry Andric   default:
247349cc55cSDimitry Andric     return CudaVersion::NEW;
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)2510b57cec5SDimitry Andric bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
2520b57cec5SDimitry Andric   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)2550b57cec5SDimitry Andric bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2560b57cec5SDimitry Andric   switch (Feature) {
2570b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_NEW_LAUNCH:
2580b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_92;
2590b57cec5SDimitry Andric   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2600b57cec5SDimitry Andric     return Version >= CudaVersion::CUDA_101;
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric   llvm_unreachable("Unknown CUDA feature.");
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric } // namespace clang
265