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