xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Cuda.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick #include "clang/Basic/Cuda.h"
2e5dd7070Spatrick 
3e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
4e5dd7070Spatrick #include "llvm/ADT/Twine.h"
5e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
6e5dd7070Spatrick #include "llvm/Support/VersionTuple.h"
7e5dd7070Spatrick 
8e5dd7070Spatrick namespace clang {
9e5dd7070Spatrick 
10*12c85518Srobert struct CudaVersionMapEntry {
11*12c85518Srobert   const char *Name;
12*12c85518Srobert   CudaVersion Version;
13*12c85518Srobert   llvm::VersionTuple TVersion;
14*12c85518Srobert };
15*12c85518Srobert #define CUDA_ENTRY(major, minor)                                               \
16*12c85518Srobert   {                                                                            \
17*12c85518Srobert #major "." #minor, CudaVersion::CUDA_##major##minor,                       \
18*12c85518Srobert         llvm::VersionTuple(major, minor)                                       \
19e5dd7070Spatrick   }
20*12c85518Srobert 
21*12c85518Srobert static const CudaVersionMapEntry CudaNameVersionMap[] = {
22*12c85518Srobert     CUDA_ENTRY(7, 0),
23*12c85518Srobert     CUDA_ENTRY(7, 5),
24*12c85518Srobert     CUDA_ENTRY(8, 0),
25*12c85518Srobert     CUDA_ENTRY(9, 0),
26*12c85518Srobert     CUDA_ENTRY(9, 1),
27*12c85518Srobert     CUDA_ENTRY(9, 2),
28*12c85518Srobert     CUDA_ENTRY(10, 0),
29*12c85518Srobert     CUDA_ENTRY(10, 1),
30*12c85518Srobert     CUDA_ENTRY(10, 2),
31*12c85518Srobert     CUDA_ENTRY(11, 0),
32*12c85518Srobert     CUDA_ENTRY(11, 1),
33*12c85518Srobert     CUDA_ENTRY(11, 2),
34*12c85518Srobert     CUDA_ENTRY(11, 3),
35*12c85518Srobert     CUDA_ENTRY(11, 4),
36*12c85518Srobert     CUDA_ENTRY(11, 5),
37*12c85518Srobert     CUDA_ENTRY(11, 6),
38*12c85518Srobert     CUDA_ENTRY(11, 7),
39*12c85518Srobert     CUDA_ENTRY(11, 8),
40*12c85518Srobert     {"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
41*12c85518Srobert     {"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
42*12c85518Srobert };
43*12c85518Srobert #undef CUDA_ENTRY
44*12c85518Srobert 
CudaVersionToString(CudaVersion V)45*12c85518Srobert const char *CudaVersionToString(CudaVersion V) {
46*12c85518Srobert   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
47*12c85518Srobert     if (I->Version == V)
48*12c85518Srobert       return I->Name;
49*12c85518Srobert 
50*12c85518Srobert   return CudaVersionToString(CudaVersion::UNKNOWN);
51e5dd7070Spatrick }
52e5dd7070Spatrick 
CudaStringToVersion(const llvm::Twine & S)53e5dd7070Spatrick CudaVersion CudaStringToVersion(const llvm::Twine &S) {
54*12c85518Srobert   std::string VS = S.str();
55*12c85518Srobert   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
56*12c85518Srobert     if (I->Name == VS)
57*12c85518Srobert       return I->Version;
58*12c85518Srobert   return CudaVersion::UNKNOWN;
59*12c85518Srobert }
60*12c85518Srobert 
ToCudaVersion(llvm::VersionTuple Version)61*12c85518Srobert CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
62*12c85518Srobert   for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
63*12c85518Srobert     if (I->TVersion == Version)
64*12c85518Srobert       return I->Version;
65*12c85518Srobert   return CudaVersion::UNKNOWN;
66e5dd7070Spatrick }
67e5dd7070Spatrick 
68a9ac8606Spatrick namespace {
69ec727ea7Spatrick struct CudaArchToStringMap {
70ec727ea7Spatrick   CudaArch arch;
71ec727ea7Spatrick   const char *arch_name;
72ec727ea7Spatrick   const char *virtual_arch_name;
73ec727ea7Spatrick };
74a9ac8606Spatrick } // namespace
75ec727ea7Spatrick 
76ec727ea7Spatrick #define SM2(sm, ca)                                                            \
77ec727ea7Spatrick   { CudaArch::SM_##sm, "sm_" #sm, ca }
78ec727ea7Spatrick #define SM(sm) SM2(sm, "compute_" #sm)
79ec727ea7Spatrick #define GFX(gpu)                                                               \
80ec727ea7Spatrick   { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
81a9ac8606Spatrick static const CudaArchToStringMap arch_names[] = {
82ec727ea7Spatrick     // clang-format off
83a9ac8606Spatrick     {CudaArch::UNUSED, "", ""},
84ec727ea7Spatrick     SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
85ec727ea7Spatrick     SM(30), SM(32), SM(35), SM(37),  // Kepler
86ec727ea7Spatrick     SM(50), SM(52), SM(53),          // Maxwell
87ec727ea7Spatrick     SM(60), SM(61), SM(62),          // Pascal
88ec727ea7Spatrick     SM(70), SM(72),                  // Volta
89ec727ea7Spatrick     SM(75),                          // Turing
90a9ac8606Spatrick     SM(80), SM(86),                  // Ampere
91*12c85518Srobert     SM(87),                          // Jetson/Drive AGX Orin
92*12c85518Srobert     SM(89),                          // Ada Lovelace
93*12c85518Srobert     SM(90),                          // Hopper
94a9ac8606Spatrick     GFX(600),  // gfx600
95a9ac8606Spatrick     GFX(601),  // gfx601
96a9ac8606Spatrick     GFX(602),  // gfx602
97a9ac8606Spatrick     GFX(700),  // gfx700
98a9ac8606Spatrick     GFX(701),  // gfx701
99a9ac8606Spatrick     GFX(702),  // gfx702
100a9ac8606Spatrick     GFX(703),  // gfx703
101a9ac8606Spatrick     GFX(704),  // gfx704
102a9ac8606Spatrick     GFX(705),  // gfx705
103a9ac8606Spatrick     GFX(801),  // gfx801
104a9ac8606Spatrick     GFX(802),  // gfx802
105a9ac8606Spatrick     GFX(803),  // gfx803
106a9ac8606Spatrick     GFX(805),  // gfx805
107a9ac8606Spatrick     GFX(810),  // gfx810
108a9ac8606Spatrick     GFX(900),  // gfx900
109a9ac8606Spatrick     GFX(902),  // gfx902
110a9ac8606Spatrick     GFX(904),  // gfx903
111a9ac8606Spatrick     GFX(906),  // gfx906
112a9ac8606Spatrick     GFX(908),  // gfx908
113a9ac8606Spatrick     GFX(909),  // gfx909
114a9ac8606Spatrick     GFX(90a),  // gfx90a
115a9ac8606Spatrick     GFX(90c),  // gfx90c
116*12c85518Srobert     GFX(940),  // gfx940
117a9ac8606Spatrick     GFX(1010), // gfx1010
118a9ac8606Spatrick     GFX(1011), // gfx1011
119a9ac8606Spatrick     GFX(1012), // gfx1012
120a9ac8606Spatrick     GFX(1013), // gfx1013
121a9ac8606Spatrick     GFX(1030), // gfx1030
122a9ac8606Spatrick     GFX(1031), // gfx1031
123a9ac8606Spatrick     GFX(1032), // gfx1032
124a9ac8606Spatrick     GFX(1033), // gfx1033
125a9ac8606Spatrick     GFX(1034), // gfx1034
126a9ac8606Spatrick     GFX(1035), // gfx1035
127*12c85518Srobert     GFX(1036), // gfx1036
128*12c85518Srobert     GFX(1100), // gfx1100
129*12c85518Srobert     GFX(1101), // gfx1101
130*12c85518Srobert     GFX(1102), // gfx1102
131*12c85518Srobert     GFX(1103), // gfx1103
132*12c85518Srobert     {CudaArch::Generic, "generic", ""},
133ec727ea7Spatrick     // clang-format on
134ec727ea7Spatrick };
135ec727ea7Spatrick #undef SM
136ec727ea7Spatrick #undef SM2
137ec727ea7Spatrick #undef GFX
138ec727ea7Spatrick 
CudaArchToString(CudaArch A)139e5dd7070Spatrick const char *CudaArchToString(CudaArch A) {
140ec727ea7Spatrick   auto result = std::find_if(
141ec727ea7Spatrick       std::begin(arch_names), std::end(arch_names),
142ec727ea7Spatrick       [A](const CudaArchToStringMap &map) { return A == map.arch; });
143ec727ea7Spatrick   if (result == std::end(arch_names))
144e5dd7070Spatrick     return "unknown";
145ec727ea7Spatrick   return result->arch_name;
146e5dd7070Spatrick }
147ec727ea7Spatrick 
CudaArchToVirtualArchString(CudaArch A)148ec727ea7Spatrick const char *CudaArchToVirtualArchString(CudaArch A) {
149ec727ea7Spatrick   auto result = std::find_if(
150ec727ea7Spatrick       std::begin(arch_names), std::end(arch_names),
151ec727ea7Spatrick       [A](const CudaArchToStringMap &map) { return A == map.arch; });
152ec727ea7Spatrick   if (result == std::end(arch_names))
153ec727ea7Spatrick     return "unknown";
154ec727ea7Spatrick   return result->virtual_arch_name;
155e5dd7070Spatrick }
156e5dd7070Spatrick 
StringToCudaArch(llvm::StringRef S)157e5dd7070Spatrick CudaArch StringToCudaArch(llvm::StringRef S) {
158ec727ea7Spatrick   auto result = std::find_if(
159ec727ea7Spatrick       std::begin(arch_names), std::end(arch_names),
160ec727ea7Spatrick       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
161ec727ea7Spatrick   if (result == std::end(arch_names))
162ec727ea7Spatrick     return CudaArch::UNKNOWN;
163ec727ea7Spatrick   return result->arch;
164e5dd7070Spatrick }
165e5dd7070Spatrick 
MinVersionForCudaArch(CudaArch A)166e5dd7070Spatrick CudaVersion MinVersionForCudaArch(CudaArch A) {
167ec727ea7Spatrick   if (A == CudaArch::UNKNOWN)
168e5dd7070Spatrick     return CudaVersion::UNKNOWN;
169ec727ea7Spatrick 
170ec727ea7Spatrick   // AMD GPUs do not depend on CUDA versions.
171ec727ea7Spatrick   if (IsAMDGpuArch(A))
172ec727ea7Spatrick     return CudaVersion::CUDA_70;
173ec727ea7Spatrick 
174ec727ea7Spatrick   switch (A) {
175e5dd7070Spatrick   case CudaArch::SM_20:
176e5dd7070Spatrick   case CudaArch::SM_21:
177e5dd7070Spatrick   case CudaArch::SM_30:
178e5dd7070Spatrick   case CudaArch::SM_32:
179e5dd7070Spatrick   case CudaArch::SM_35:
180e5dd7070Spatrick   case CudaArch::SM_37:
181e5dd7070Spatrick   case CudaArch::SM_50:
182e5dd7070Spatrick   case CudaArch::SM_52:
183e5dd7070Spatrick   case CudaArch::SM_53:
184e5dd7070Spatrick     return CudaVersion::CUDA_70;
185e5dd7070Spatrick   case CudaArch::SM_60:
186e5dd7070Spatrick   case CudaArch::SM_61:
187e5dd7070Spatrick   case CudaArch::SM_62:
188e5dd7070Spatrick     return CudaVersion::CUDA_80;
189e5dd7070Spatrick   case CudaArch::SM_70:
190e5dd7070Spatrick     return CudaVersion::CUDA_90;
191e5dd7070Spatrick   case CudaArch::SM_72:
192e5dd7070Spatrick     return CudaVersion::CUDA_91;
193e5dd7070Spatrick   case CudaArch::SM_75:
194e5dd7070Spatrick     return CudaVersion::CUDA_100;
195ec727ea7Spatrick   case CudaArch::SM_80:
196ec727ea7Spatrick     return CudaVersion::CUDA_110;
197a9ac8606Spatrick   case CudaArch::SM_86:
198a9ac8606Spatrick     return CudaVersion::CUDA_111;
199*12c85518Srobert   case CudaArch::SM_87:
200*12c85518Srobert     return CudaVersion::CUDA_114;
201*12c85518Srobert   case CudaArch::SM_89:
202*12c85518Srobert   case CudaArch::SM_90:
203*12c85518Srobert     return CudaVersion::CUDA_118;
204ec727ea7Spatrick   default:
205e5dd7070Spatrick     llvm_unreachable("invalid enum");
206e5dd7070Spatrick   }
207ec727ea7Spatrick }
208e5dd7070Spatrick 
MaxVersionForCudaArch(CudaArch A)209e5dd7070Spatrick CudaVersion MaxVersionForCudaArch(CudaArch A) {
210ec727ea7Spatrick   // AMD GPUs do not depend on CUDA versions.
211ec727ea7Spatrick   if (IsAMDGpuArch(A))
212*12c85518Srobert     return CudaVersion::NEW;
213ec727ea7Spatrick 
214e5dd7070Spatrick   switch (A) {
215e5dd7070Spatrick   case CudaArch::UNKNOWN:
216e5dd7070Spatrick     return CudaVersion::UNKNOWN;
217e5dd7070Spatrick   case CudaArch::SM_20:
218e5dd7070Spatrick   case CudaArch::SM_21:
219e5dd7070Spatrick     return CudaVersion::CUDA_80;
220*12c85518Srobert   case CudaArch::SM_30:
221ec727ea7Spatrick     return CudaVersion::CUDA_110;
222e5dd7070Spatrick   default:
223*12c85518Srobert     return CudaVersion::NEW;
224e5dd7070Spatrick   }
225e5dd7070Spatrick }
226e5dd7070Spatrick 
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)227e5dd7070Spatrick bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
228e5dd7070Spatrick   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
229e5dd7070Spatrick }
230e5dd7070Spatrick 
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)231e5dd7070Spatrick bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
232e5dd7070Spatrick   switch (Feature) {
233e5dd7070Spatrick   case CudaFeature::CUDA_USES_NEW_LAUNCH:
234e5dd7070Spatrick     return Version >= CudaVersion::CUDA_92;
235e5dd7070Spatrick   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
236e5dd7070Spatrick     return Version >= CudaVersion::CUDA_101;
237e5dd7070Spatrick   }
238e5dd7070Spatrick   llvm_unreachable("Unknown CUDA feature.");
239e5dd7070Spatrick }
240e5dd7070Spatrick } // namespace clang
241