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), // gfx600
76 GFX(601), // gfx601
77 GFX(602), // gfx602
78 GFX(700), // gfx700
79 GFX(701), // gfx701
80 GFX(702), // gfx702
81 GFX(703), // gfx703
82 GFX(704), // gfx704
83 GFX(705), // gfx705
84 GFX(801), // gfx801
85 GFX(802), // gfx802
86 GFX(803), // gfx803
87 GFX(805), // gfx805
88 GFX(810), // gfx810
89 GFX(900), // gfx900
90 GFX(902), // gfx902
91 GFX(904), // gfx903
92 GFX(906), // gfx906
93 GFX(908), // gfx908
94 GFX(909), // gfx909
95 GFX(90c), // gfx90c
96 GFX(1010), // gfx1010
97 GFX(1011), // gfx1011
98 GFX(1012), // gfx1012
99 GFX(1030), // gfx1030
100 GFX(1031), // gfx1031
101 GFX(1032), // gfx1032
102 GFX(1033), // gfx1033
103 // clang-format on
104 };
105 #undef SM
106 #undef SM2
107 #undef GFX
108
CudaArchToString(CudaArch A)109 const char *CudaArchToString(CudaArch A) {
110 auto result = std::find_if(
111 std::begin(arch_names), std::end(arch_names),
112 [A](const CudaArchToStringMap &map) { return A == map.arch; });
113 if (result == std::end(arch_names))
114 return "unknown";
115 return result->arch_name;
116 }
117
CudaArchToVirtualArchString(CudaArch A)118 const char *CudaArchToVirtualArchString(CudaArch A) {
119 auto result = std::find_if(
120 std::begin(arch_names), std::end(arch_names),
121 [A](const CudaArchToStringMap &map) { return A == map.arch; });
122 if (result == std::end(arch_names))
123 return "unknown";
124 return result->virtual_arch_name;
125 }
126
StringToCudaArch(llvm::StringRef S)127 CudaArch StringToCudaArch(llvm::StringRef S) {
128 auto result = std::find_if(
129 std::begin(arch_names), std::end(arch_names),
130 [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
131 if (result == std::end(arch_names))
132 return CudaArch::UNKNOWN;
133 return result->arch;
134 }
135
MinVersionForCudaArch(CudaArch A)136 CudaVersion MinVersionForCudaArch(CudaArch A) {
137 if (A == CudaArch::UNKNOWN)
138 return CudaVersion::UNKNOWN;
139
140 // AMD GPUs do not depend on CUDA versions.
141 if (IsAMDGpuArch(A))
142 return CudaVersion::CUDA_70;
143
144 switch (A) {
145 case CudaArch::SM_20:
146 case CudaArch::SM_21:
147 case CudaArch::SM_30:
148 case CudaArch::SM_32:
149 case CudaArch::SM_35:
150 case CudaArch::SM_37:
151 case CudaArch::SM_50:
152 case CudaArch::SM_52:
153 case CudaArch::SM_53:
154 return CudaVersion::CUDA_70;
155 case CudaArch::SM_60:
156 case CudaArch::SM_61:
157 case CudaArch::SM_62:
158 return CudaVersion::CUDA_80;
159 case CudaArch::SM_70:
160 return CudaVersion::CUDA_90;
161 case CudaArch::SM_72:
162 return CudaVersion::CUDA_91;
163 case CudaArch::SM_75:
164 return CudaVersion::CUDA_100;
165 case CudaArch::SM_80:
166 return CudaVersion::CUDA_110;
167 default:
168 llvm_unreachable("invalid enum");
169 }
170 }
171
MaxVersionForCudaArch(CudaArch A)172 CudaVersion MaxVersionForCudaArch(CudaArch A) {
173 // AMD GPUs do not depend on CUDA versions.
174 if (IsAMDGpuArch(A))
175 return CudaVersion::LATEST;
176
177 switch (A) {
178 case CudaArch::UNKNOWN:
179 return CudaVersion::UNKNOWN;
180 case CudaArch::SM_20:
181 case CudaArch::SM_21:
182 return CudaVersion::CUDA_80;
183 default:
184 return CudaVersion::LATEST;
185 }
186 }
187
ToCudaVersion(llvm::VersionTuple Version)188 CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
189 int IVer =
190 Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
191 switch(IVer) {
192 case 70:
193 return CudaVersion::CUDA_70;
194 case 75:
195 return CudaVersion::CUDA_75;
196 case 80:
197 return CudaVersion::CUDA_80;
198 case 90:
199 return CudaVersion::CUDA_90;
200 case 91:
201 return CudaVersion::CUDA_91;
202 case 92:
203 return CudaVersion::CUDA_92;
204 case 100:
205 return CudaVersion::CUDA_100;
206 case 101:
207 return CudaVersion::CUDA_101;
208 case 102:
209 return CudaVersion::CUDA_102;
210 case 110:
211 return CudaVersion::CUDA_110;
212 default:
213 return CudaVersion::UNKNOWN;
214 }
215 }
216
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)217 bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
218 return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
219 }
220
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)221 bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
222 switch (Feature) {
223 case CudaFeature::CUDA_USES_NEW_LAUNCH:
224 return Version >= CudaVersion::CUDA_92;
225 case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
226 return Version >= CudaVersion::CUDA_101;
227 }
228 llvm_unreachable("Unknown CUDA feature.");
229 }
230 } // namespace clang
231