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