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
9 namespace clang {
10
CudaVersionToString(CudaVersion V)11 const 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 }
36 llvm_unreachable("invalid enum");
37 }
38
CudaStringToVersion(const llvm::Twine & S)39 CudaVersion CudaStringToVersion(const llvm::Twine &S) {
40 return llvm::StringSwitch<CudaVersion>(S.str())
41 .Case("7.0", CudaVersion::CUDA_70)
42 .Case("7.5", CudaVersion::CUDA_75)
43 .Case("8.0", CudaVersion::CUDA_80)
44 .Case("9.0", CudaVersion::CUDA_90)
45 .Case("9.1", CudaVersion::CUDA_91)
46 .Case("9.2", CudaVersion::CUDA_92)
47 .Case("10.0", CudaVersion::CUDA_100)
48 .Case("10.1", CudaVersion::CUDA_101)
49 .Case("10.2", CudaVersion::CUDA_102)
50 .Case("11.0", CudaVersion::CUDA_110)
51 .Default(CudaVersion::UNKNOWN);
52 }
53
54 struct CudaArchToStringMap {
55 CudaArch arch;
56 const char *arch_name;
57 const char *virtual_arch_name;
58 };
59
60 #define SM2(sm, ca) \
61 { CudaArch::SM_##sm, "sm_" #sm, ca }
62 #define SM(sm) SM2(sm, "compute_" #sm)
63 #define GFX(gpu) \
64 { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
65 CudaArchToStringMap arch_names[] = {
66 // clang-format off
67 {CudaArch::UNUSED, "", ""},
68 SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
69 SM(30), SM(32), SM(35), SM(37), // Kepler
70 SM(50), SM(52), SM(53), // Maxwell
71 SM(60), SM(61), SM(62), // Pascal
72 SM(70), SM(72), // Volta
73 SM(75), // Turing
74 SM(80), // Ampere
75 GFX(600), // tahiti
76 GFX(601), // pitcairn, verde
77 GFX(602), // oland, hainan
78 GFX(700), // kaveri
79 GFX(701), // hawaii
80 GFX(702), // 290,290x,R390,R390x
81 GFX(703), // kabini mullins
82 GFX(704), // bonaire
83 GFX(705),
84 GFX(801), // carrizo
85 GFX(802), // tonga,iceland
86 GFX(803), // fiji,polaris10
87 GFX(805), // tongapro
88 GFX(810), // stoney
89 GFX(900), // vega, instinct
90 GFX(902), GFX(904), GFX(906), GFX(908), GFX(909), GFX(90c),
91 GFX(1010), GFX(1011), GFX(1012), GFX(1030), GFX(1031), GFX(1032), GFX(1033)
92 // clang-format on
93 };
94 #undef SM
95 #undef SM2
96 #undef GFX
97
CudaArchToString(CudaArch A)98 const char *CudaArchToString(CudaArch A) {
99 auto result = std::find_if(
100 std::begin(arch_names), std::end(arch_names),
101 [A](const CudaArchToStringMap &map) { return A == map.arch; });
102 if (result == std::end(arch_names))
103 return "unknown";
104 return result->arch_name;
105 }
106
CudaArchToVirtualArchString(CudaArch A)107 const char *CudaArchToVirtualArchString(CudaArch A) {
108 auto result = std::find_if(
109 std::begin(arch_names), std::end(arch_names),
110 [A](const CudaArchToStringMap &map) { return A == map.arch; });
111 if (result == std::end(arch_names))
112 return "unknown";
113 return result->virtual_arch_name;
114 }
115
StringToCudaArch(llvm::StringRef S)116 CudaArch StringToCudaArch(llvm::StringRef S) {
117 auto result = std::find_if(
118 std::begin(arch_names), std::end(arch_names),
119 [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
120 if (result == std::end(arch_names))
121 return CudaArch::UNKNOWN;
122 return result->arch;
123 }
124
MinVersionForCudaArch(CudaArch A)125 CudaVersion MinVersionForCudaArch(CudaArch A) {
126 if (A == CudaArch::UNKNOWN)
127 return CudaVersion::UNKNOWN;
128
129 // AMD GPUs do not depend on CUDA versions.
130 if (IsAMDGpuArch(A))
131 return CudaVersion::CUDA_70;
132
133 switch (A) {
134 case CudaArch::SM_20:
135 case CudaArch::SM_21:
136 case CudaArch::SM_30:
137 case CudaArch::SM_32:
138 case CudaArch::SM_35:
139 case CudaArch::SM_37:
140 case CudaArch::SM_50:
141 case CudaArch::SM_52:
142 case CudaArch::SM_53:
143 return CudaVersion::CUDA_70;
144 case CudaArch::SM_60:
145 case CudaArch::SM_61:
146 case CudaArch::SM_62:
147 return CudaVersion::CUDA_80;
148 case CudaArch::SM_70:
149 return CudaVersion::CUDA_90;
150 case CudaArch::SM_72:
151 return CudaVersion::CUDA_91;
152 case CudaArch::SM_75:
153 return CudaVersion::CUDA_100;
154 case CudaArch::SM_80:
155 return CudaVersion::CUDA_110;
156 default:
157 llvm_unreachable("invalid enum");
158 }
159 }
160
MaxVersionForCudaArch(CudaArch A)161 CudaVersion MaxVersionForCudaArch(CudaArch A) {
162 // AMD GPUs do not depend on CUDA versions.
163 if (IsAMDGpuArch(A))
164 return CudaVersion::LATEST;
165
166 switch (A) {
167 case CudaArch::UNKNOWN:
168 return CudaVersion::UNKNOWN;
169 case CudaArch::SM_20:
170 case CudaArch::SM_21:
171 return CudaVersion::CUDA_80;
172 default:
173 return CudaVersion::LATEST;
174 }
175 }
176
ToCudaVersion(llvm::VersionTuple Version)177 CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
178 int IVer =
179 Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
180 switch(IVer) {
181 case 70:
182 return CudaVersion::CUDA_70;
183 case 75:
184 return CudaVersion::CUDA_75;
185 case 80:
186 return CudaVersion::CUDA_80;
187 case 90:
188 return CudaVersion::CUDA_90;
189 case 91:
190 return CudaVersion::CUDA_91;
191 case 92:
192 return CudaVersion::CUDA_92;
193 case 100:
194 return CudaVersion::CUDA_100;
195 case 101:
196 return CudaVersion::CUDA_101;
197 case 102:
198 return CudaVersion::CUDA_102;
199 case 110:
200 return CudaVersion::CUDA_110;
201 default:
202 return CudaVersion::UNKNOWN;
203 }
204 }
205
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)206 bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
207 return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
208 }
209
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)210 bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
211 switch (Feature) {
212 case CudaFeature::CUDA_USES_NEW_LAUNCH:
213 return Version >= CudaVersion::CUDA_92;
214 case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
215 return Version >= CudaVersion::CUDA_101;
216 }
217 llvm_unreachable("Unknown CUDA feature.");
218 }
219 } // namespace clang
220