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