1#include "clang/Basic/Cuda.h"
2
3#include "llvm/ADT/Twine.h"
4#include "llvm/Support/ErrorHandling.h"
5#include "llvm/Support/VersionTuple.h"
6
7namespace clang {
8
9struct CudaVersionMapEntry {
10 const char *Name;
11 CudaVersion Version;
12 llvm::VersionTuple TVersion;
13};
14#define CUDA_ENTRY(major, minor) \
15 { \
16 #major "." #minor, CudaVersion::CUDA_##major##minor, \
17 llvm::VersionTuple(major, minor) \
18 }
19
20static const CudaVersionMapEntry CudaNameVersionMap[] = {
21 CUDA_ENTRY(7, 0),
22 CUDA_ENTRY(7, 5),
23 CUDA_ENTRY(8, 0),
24 CUDA_ENTRY(9, 0),
25 CUDA_ENTRY(9, 1),
26 CUDA_ENTRY(9, 2),
27 CUDA_ENTRY(10, 0),
28 CUDA_ENTRY(10, 1),
29 CUDA_ENTRY(10, 2),
30 CUDA_ENTRY(11, 0),
31 CUDA_ENTRY(11, 1),
32 CUDA_ENTRY(11, 2),
33 CUDA_ENTRY(11, 3),
34 CUDA_ENTRY(11, 4),
35 CUDA_ENTRY(11, 5),
36 CUDA_ENTRY(11, 6),
37 CUDA_ENTRY(11, 7),
38 CUDA_ENTRY(11, 8),
39 CUDA_ENTRY(12, 0),
40 CUDA_ENTRY(12, 1),
41 CUDA_ENTRY(12, 2),
42 CUDA_ENTRY(12, 3),
43 CUDA_ENTRY(12, 4),
44 CUDA_ENTRY(12, 5),
45 CUDA_ENTRY(12, 6),
46 CUDA_ENTRY(12, 8),
47 CUDA_ENTRY(12, 9),
48 CUDA_ENTRY(13, 0),
49 CUDA_ENTRY(13, 1),
50 CUDA_ENTRY(13, 2),
51 {.Name: "", .Version: CudaVersion::NEW, .TVersion: llvm::VersionTuple(std::numeric_limits<int>::max())},
52 {.Name: "unknown", .Version: CudaVersion::UNKNOWN, .TVersion: {}} // End of list tombstone.
53};
54#undef CUDA_ENTRY
55
56const char *CudaVersionToString(CudaVersion V) {
57 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
58 if (I->Version == V)
59 return I->Name;
60
61 return CudaVersionToString(V: CudaVersion::UNKNOWN);
62}
63
64CudaVersion CudaStringToVersion(const llvm::Twine &S) {
65 std::string VS = S.str();
66 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
67 if (I->Name == VS)
68 return I->Version;
69 return CudaVersion::UNKNOWN;
70}
71
72CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
73 for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
74 if (I->TVersion == Version)
75 return I->Version;
76 return CudaVersion::UNKNOWN;
77}
78
79CudaVersion MinVersionForOffloadArch(OffloadArch A) {
80 if (A == OffloadArch::Unknown)
81 return CudaVersion::UNKNOWN;
82
83 // AMD GPUs do not depend on CUDA versions.
84 if (IsAMDOffloadArch(A))
85 return CudaVersion::CUDA_70;
86
87 switch (A) {
88 case OffloadArch::SM_20:
89 case OffloadArch::SM_21:
90 case OffloadArch::SM_30:
91 case OffloadArch::SM_32_:
92 case OffloadArch::SM_35:
93 case OffloadArch::SM_37:
94 case OffloadArch::SM_50:
95 case OffloadArch::SM_52:
96 case OffloadArch::SM_53:
97 return CudaVersion::CUDA_70;
98 case OffloadArch::SM_60:
99 case OffloadArch::SM_61:
100 case OffloadArch::SM_62:
101 return CudaVersion::CUDA_80;
102 case OffloadArch::SM_70:
103 return CudaVersion::CUDA_90;
104 case OffloadArch::SM_72:
105 return CudaVersion::CUDA_91;
106 case OffloadArch::SM_75:
107 return CudaVersion::CUDA_100;
108 case OffloadArch::SM_80:
109 return CudaVersion::CUDA_110;
110 case OffloadArch::SM_86:
111 return CudaVersion::CUDA_111;
112 case OffloadArch::SM_87:
113 return CudaVersion::CUDA_114;
114 case OffloadArch::SM_89:
115 case OffloadArch::SM_90:
116 return CudaVersion::CUDA_118;
117 case OffloadArch::SM_90a:
118 return CudaVersion::CUDA_120;
119 case OffloadArch::SM_100:
120 case OffloadArch::SM_100a:
121 case OffloadArch::SM_101:
122 case OffloadArch::SM_101a:
123 case OffloadArch::SM_120:
124 case OffloadArch::SM_120a:
125 return CudaVersion::CUDA_128;
126 case OffloadArch::SM_100f:
127 case OffloadArch::SM_101f:
128 case OffloadArch::SM_103:
129 case OffloadArch::SM_103a:
130 case OffloadArch::SM_103f:
131 case OffloadArch::SM_120f:
132 case OffloadArch::SM_121:
133 case OffloadArch::SM_121a:
134 case OffloadArch::SM_121f:
135 return CudaVersion::CUDA_129;
136 case OffloadArch::SM_88:
137 case OffloadArch::SM_110:
138 case OffloadArch::SM_110a:
139 case OffloadArch::SM_110f:
140 return CudaVersion::CUDA_130;
141 default:
142 llvm_unreachable("invalid enum");
143 }
144}
145
146CudaVersion MaxVersionForOffloadArch(OffloadArch A) {
147 // AMD GPUs do not depend on CUDA versions.
148 if (IsAMDOffloadArch(A))
149 return CudaVersion::NEW;
150
151 switch (A) {
152 case OffloadArch::Unknown:
153 return CudaVersion::UNKNOWN;
154 case OffloadArch::SM_20:
155 case OffloadArch::SM_21:
156 return CudaVersion::CUDA_80;
157 case OffloadArch::SM_30:
158 case OffloadArch::SM_32_:
159 return CudaVersion::CUDA_102;
160 case OffloadArch::SM_35:
161 case OffloadArch::SM_37:
162 return CudaVersion::CUDA_118;
163 case OffloadArch::SM_101:
164 case OffloadArch::SM_101a:
165 case OffloadArch::SM_101f:
166 return CudaVersion::CUDA_129;
167 default:
168 return CudaVersion::NEW;
169 }
170}
171
172bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
173 return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
174}
175
176bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
177 switch (Feature) {
178 case CudaFeature::CUDA_USES_NEW_LAUNCH:
179 return Version >= CudaVersion::CUDA_92;
180 case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
181 return Version >= CudaVersion::CUDA_101;
182 }
183 llvm_unreachable("Unknown CUDA feature.");
184}
185
186unsigned CudaArchToID(OffloadArch Arch) {
187 switch (Arch) {
188 case OffloadArch::SM_20:
189 return 200;
190 case OffloadArch::SM_21:
191 return 210;
192 case OffloadArch::SM_30:
193 return 300;
194 case OffloadArch::SM_32_:
195 return 320;
196 case OffloadArch::SM_35:
197 return 350;
198 case OffloadArch::SM_37:
199 return 370;
200 case OffloadArch::SM_50:
201 return 500;
202 case OffloadArch::SM_52:
203 return 520;
204 case OffloadArch::SM_53:
205 return 530;
206 case OffloadArch::SM_60:
207 return 600;
208 case OffloadArch::SM_61:
209 return 610;
210 case OffloadArch::SM_62:
211 return 620;
212 case OffloadArch::SM_70:
213 return 700;
214 case OffloadArch::SM_72:
215 return 720;
216 case OffloadArch::SM_75:
217 return 750;
218 case OffloadArch::SM_80:
219 return 800;
220 case OffloadArch::SM_86:
221 return 860;
222 case OffloadArch::SM_87:
223 return 870;
224 case OffloadArch::SM_88:
225 return 880;
226 case OffloadArch::SM_89:
227 return 890;
228 case OffloadArch::SM_90:
229 case OffloadArch::SM_90a:
230 return 900;
231 case OffloadArch::SM_100:
232 case OffloadArch::SM_100a:
233 case OffloadArch::SM_100f:
234 return 1000;
235 case OffloadArch::SM_101:
236 case OffloadArch::SM_101a:
237 case OffloadArch::SM_101f:
238 return 1010;
239 case OffloadArch::SM_103:
240 case OffloadArch::SM_103a:
241 case OffloadArch::SM_103f:
242 return 1030;
243 case OffloadArch::SM_110:
244 case OffloadArch::SM_110a:
245 case OffloadArch::SM_110f:
246 return 1100;
247 case OffloadArch::SM_120:
248 case OffloadArch::SM_120a:
249 case OffloadArch::SM_120f:
250 return 1200;
251 case OffloadArch::SM_121:
252 case OffloadArch::SM_121a:
253 case OffloadArch::SM_121f:
254 return 1210;
255 default:
256 break;
257 }
258 llvm_unreachable("invalid NVIDIA GPU architecture");
259}
260
261bool IsNVIDIAAcceleratedOffloadArch(OffloadArch Arch) {
262 switch (Arch) {
263 case OffloadArch::SM_90a:
264 case OffloadArch::SM_100a:
265 case OffloadArch::SM_101a:
266 case OffloadArch::SM_103a:
267 case OffloadArch::SM_110a:
268 case OffloadArch::SM_120a:
269 case OffloadArch::SM_121a:
270 return true;
271 default:
272 return false;
273 }
274}
275
276bool IsNVIDIAFamilySpecificOffloadArch(OffloadArch Arch) {
277 if (IsNVIDIAAcceleratedOffloadArch(Arch))
278 return true;
279 switch (Arch) {
280 case OffloadArch::SM_100f:
281 case OffloadArch::SM_101f:
282 case OffloadArch::SM_103f:
283 case OffloadArch::SM_110f:
284 case OffloadArch::SM_120f:
285 case OffloadArch::SM_121f:
286 return true;
287 default:
288 return false;
289 }
290}
291} // namespace clang
292