17330f729Sjoerg #include "clang/Basic/Cuda.h"
27330f729Sjoerg
37330f729Sjoerg #include "llvm/ADT/StringRef.h"
47330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
5*e038c9c4Sjoerg #include "llvm/ADT/Twine.h"
67330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
77330f729Sjoerg #include "llvm/Support/VersionTuple.h"
87330f729Sjoerg
97330f729Sjoerg namespace clang {
107330f729Sjoerg
CudaVersionToString(CudaVersion V)117330f729Sjoerg const char *CudaVersionToString(CudaVersion V) {
127330f729Sjoerg switch (V) {
137330f729Sjoerg case CudaVersion::UNKNOWN:
147330f729Sjoerg return "unknown";
157330f729Sjoerg case CudaVersion::CUDA_70:
167330f729Sjoerg return "7.0";
177330f729Sjoerg case CudaVersion::CUDA_75:
187330f729Sjoerg return "7.5";
197330f729Sjoerg case CudaVersion::CUDA_80:
207330f729Sjoerg return "8.0";
217330f729Sjoerg case CudaVersion::CUDA_90:
227330f729Sjoerg return "9.0";
237330f729Sjoerg case CudaVersion::CUDA_91:
247330f729Sjoerg return "9.1";
257330f729Sjoerg case CudaVersion::CUDA_92:
267330f729Sjoerg return "9.2";
277330f729Sjoerg case CudaVersion::CUDA_100:
287330f729Sjoerg return "10.0";
297330f729Sjoerg case CudaVersion::CUDA_101:
307330f729Sjoerg return "10.1";
31*e038c9c4Sjoerg case CudaVersion::CUDA_102:
32*e038c9c4Sjoerg return "10.2";
33*e038c9c4Sjoerg case CudaVersion::CUDA_110:
34*e038c9c4Sjoerg return "11.0";
35*e038c9c4Sjoerg case CudaVersion::CUDA_111:
36*e038c9c4Sjoerg return "11.1";
37*e038c9c4Sjoerg case CudaVersion::CUDA_112:
38*e038c9c4Sjoerg return "11.2";
397330f729Sjoerg }
407330f729Sjoerg llvm_unreachable("invalid enum");
417330f729Sjoerg }
427330f729Sjoerg
CudaStringToVersion(const llvm::Twine & S)43*e038c9c4Sjoerg CudaVersion CudaStringToVersion(const llvm::Twine &S) {
44*e038c9c4Sjoerg return llvm::StringSwitch<CudaVersion>(S.str())
457330f729Sjoerg .Case("7.0", CudaVersion::CUDA_70)
467330f729Sjoerg .Case("7.5", CudaVersion::CUDA_75)
477330f729Sjoerg .Case("8.0", CudaVersion::CUDA_80)
487330f729Sjoerg .Case("9.0", CudaVersion::CUDA_90)
497330f729Sjoerg .Case("9.1", CudaVersion::CUDA_91)
507330f729Sjoerg .Case("9.2", CudaVersion::CUDA_92)
517330f729Sjoerg .Case("10.0", CudaVersion::CUDA_100)
52*e038c9c4Sjoerg .Case("10.1", CudaVersion::CUDA_101)
53*e038c9c4Sjoerg .Case("10.2", CudaVersion::CUDA_102)
54*e038c9c4Sjoerg .Case("11.0", CudaVersion::CUDA_110)
55*e038c9c4Sjoerg .Case("11.1", CudaVersion::CUDA_111)
56*e038c9c4Sjoerg .Case("11.2", CudaVersion::CUDA_112)
57*e038c9c4Sjoerg .Default(CudaVersion::UNKNOWN);
587330f729Sjoerg }
597330f729Sjoerg
60*e038c9c4Sjoerg namespace {
61*e038c9c4Sjoerg struct CudaArchToStringMap {
62*e038c9c4Sjoerg CudaArch arch;
63*e038c9c4Sjoerg const char *arch_name;
64*e038c9c4Sjoerg const char *virtual_arch_name;
65*e038c9c4Sjoerg };
66*e038c9c4Sjoerg } // namespace
67*e038c9c4Sjoerg
68*e038c9c4Sjoerg #define SM2(sm, ca) \
69*e038c9c4Sjoerg { CudaArch::SM_##sm, "sm_" #sm, ca }
70*e038c9c4Sjoerg #define SM(sm) SM2(sm, "compute_" #sm)
71*e038c9c4Sjoerg #define GFX(gpu) \
72*e038c9c4Sjoerg { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
73*e038c9c4Sjoerg static const CudaArchToStringMap arch_names[] = {
74*e038c9c4Sjoerg // clang-format off
75*e038c9c4Sjoerg {CudaArch::UNUSED, "", ""},
76*e038c9c4Sjoerg SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
77*e038c9c4Sjoerg SM(30), SM(32), SM(35), SM(37), // Kepler
78*e038c9c4Sjoerg SM(50), SM(52), SM(53), // Maxwell
79*e038c9c4Sjoerg SM(60), SM(61), SM(62), // Pascal
80*e038c9c4Sjoerg SM(70), SM(72), // Volta
81*e038c9c4Sjoerg SM(75), // Turing
82*e038c9c4Sjoerg SM(80), SM(86), // Ampere
83*e038c9c4Sjoerg GFX(600), // gfx600
84*e038c9c4Sjoerg GFX(601), // gfx601
85*e038c9c4Sjoerg GFX(602), // gfx602
86*e038c9c4Sjoerg GFX(700), // gfx700
87*e038c9c4Sjoerg GFX(701), // gfx701
88*e038c9c4Sjoerg GFX(702), // gfx702
89*e038c9c4Sjoerg GFX(703), // gfx703
90*e038c9c4Sjoerg GFX(704), // gfx704
91*e038c9c4Sjoerg GFX(705), // gfx705
92*e038c9c4Sjoerg GFX(801), // gfx801
93*e038c9c4Sjoerg GFX(802), // gfx802
94*e038c9c4Sjoerg GFX(803), // gfx803
95*e038c9c4Sjoerg GFX(805), // gfx805
96*e038c9c4Sjoerg GFX(810), // gfx810
97*e038c9c4Sjoerg GFX(900), // gfx900
98*e038c9c4Sjoerg GFX(902), // gfx902
99*e038c9c4Sjoerg GFX(904), // gfx903
100*e038c9c4Sjoerg GFX(906), // gfx906
101*e038c9c4Sjoerg GFX(908), // gfx908
102*e038c9c4Sjoerg GFX(909), // gfx909
103*e038c9c4Sjoerg GFX(90a), // gfx90a
104*e038c9c4Sjoerg GFX(90c), // gfx90c
105*e038c9c4Sjoerg GFX(1010), // gfx1010
106*e038c9c4Sjoerg GFX(1011), // gfx1011
107*e038c9c4Sjoerg GFX(1012), // gfx1012
108*e038c9c4Sjoerg GFX(1030), // gfx1030
109*e038c9c4Sjoerg GFX(1031), // gfx1031
110*e038c9c4Sjoerg GFX(1032), // gfx1032
111*e038c9c4Sjoerg GFX(1033), // gfx1033
112*e038c9c4Sjoerg GFX(1034), // gfx1034
113*e038c9c4Sjoerg // clang-format on
114*e038c9c4Sjoerg };
115*e038c9c4Sjoerg #undef SM
116*e038c9c4Sjoerg #undef SM2
117*e038c9c4Sjoerg #undef GFX
118*e038c9c4Sjoerg
CudaArchToString(CudaArch A)1197330f729Sjoerg const char *CudaArchToString(CudaArch A) {
120*e038c9c4Sjoerg auto result = std::find_if(
121*e038c9c4Sjoerg std::begin(arch_names), std::end(arch_names),
122*e038c9c4Sjoerg [A](const CudaArchToStringMap &map) { return A == map.arch; });
123*e038c9c4Sjoerg if (result == std::end(arch_names))
1247330f729Sjoerg return "unknown";
125*e038c9c4Sjoerg return result->arch_name;
1267330f729Sjoerg }
127*e038c9c4Sjoerg
CudaArchToVirtualArchString(CudaArch A)128*e038c9c4Sjoerg const char *CudaArchToVirtualArchString(CudaArch A) {
129*e038c9c4Sjoerg auto result = std::find_if(
130*e038c9c4Sjoerg std::begin(arch_names), std::end(arch_names),
131*e038c9c4Sjoerg [A](const CudaArchToStringMap &map) { return A == map.arch; });
132*e038c9c4Sjoerg if (result == std::end(arch_names))
133*e038c9c4Sjoerg return "unknown";
134*e038c9c4Sjoerg return result->virtual_arch_name;
1357330f729Sjoerg }
1367330f729Sjoerg
StringToCudaArch(llvm::StringRef S)1377330f729Sjoerg CudaArch StringToCudaArch(llvm::StringRef S) {
138*e038c9c4Sjoerg auto result = std::find_if(
139*e038c9c4Sjoerg std::begin(arch_names), std::end(arch_names),
140*e038c9c4Sjoerg [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
141*e038c9c4Sjoerg if (result == std::end(arch_names))
142*e038c9c4Sjoerg return CudaArch::UNKNOWN;
143*e038c9c4Sjoerg return result->arch;
1447330f729Sjoerg }
1457330f729Sjoerg
MinVersionForCudaArch(CudaArch A)1467330f729Sjoerg CudaVersion MinVersionForCudaArch(CudaArch A) {
147*e038c9c4Sjoerg if (A == CudaArch::UNKNOWN)
1487330f729Sjoerg return CudaVersion::UNKNOWN;
149*e038c9c4Sjoerg
150*e038c9c4Sjoerg // AMD GPUs do not depend on CUDA versions.
151*e038c9c4Sjoerg if (IsAMDGpuArch(A))
152*e038c9c4Sjoerg return CudaVersion::CUDA_70;
153*e038c9c4Sjoerg
154*e038c9c4Sjoerg switch (A) {
1557330f729Sjoerg case CudaArch::SM_20:
1567330f729Sjoerg case CudaArch::SM_21:
1577330f729Sjoerg case CudaArch::SM_30:
1587330f729Sjoerg case CudaArch::SM_32:
1597330f729Sjoerg case CudaArch::SM_35:
1607330f729Sjoerg case CudaArch::SM_37:
1617330f729Sjoerg case CudaArch::SM_50:
1627330f729Sjoerg case CudaArch::SM_52:
1637330f729Sjoerg case CudaArch::SM_53:
1647330f729Sjoerg return CudaVersion::CUDA_70;
1657330f729Sjoerg case CudaArch::SM_60:
1667330f729Sjoerg case CudaArch::SM_61:
1677330f729Sjoerg case CudaArch::SM_62:
1687330f729Sjoerg return CudaVersion::CUDA_80;
1697330f729Sjoerg case CudaArch::SM_70:
1707330f729Sjoerg return CudaVersion::CUDA_90;
1717330f729Sjoerg case CudaArch::SM_72:
1727330f729Sjoerg return CudaVersion::CUDA_91;
1737330f729Sjoerg case CudaArch::SM_75:
1747330f729Sjoerg return CudaVersion::CUDA_100;
175*e038c9c4Sjoerg case CudaArch::SM_80:
176*e038c9c4Sjoerg return CudaVersion::CUDA_110;
177*e038c9c4Sjoerg case CudaArch::SM_86:
178*e038c9c4Sjoerg return CudaVersion::CUDA_111;
179*e038c9c4Sjoerg default:
1807330f729Sjoerg llvm_unreachable("invalid enum");
1817330f729Sjoerg }
182*e038c9c4Sjoerg }
1837330f729Sjoerg
MaxVersionForCudaArch(CudaArch A)1847330f729Sjoerg CudaVersion MaxVersionForCudaArch(CudaArch A) {
185*e038c9c4Sjoerg // AMD GPUs do not depend on CUDA versions.
186*e038c9c4Sjoerg if (IsAMDGpuArch(A))
187*e038c9c4Sjoerg return CudaVersion::LATEST;
188*e038c9c4Sjoerg
1897330f729Sjoerg switch (A) {
1907330f729Sjoerg case CudaArch::UNKNOWN:
1917330f729Sjoerg return CudaVersion::UNKNOWN;
1927330f729Sjoerg case CudaArch::SM_20:
1937330f729Sjoerg case CudaArch::SM_21:
1947330f729Sjoerg return CudaVersion::CUDA_80;
1957330f729Sjoerg default:
1967330f729Sjoerg return CudaVersion::LATEST;
1977330f729Sjoerg }
1987330f729Sjoerg }
1997330f729Sjoerg
ToCudaVersion(llvm::VersionTuple Version)200*e038c9c4Sjoerg CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
2017330f729Sjoerg int IVer =
2027330f729Sjoerg Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
2037330f729Sjoerg switch(IVer) {
2047330f729Sjoerg case 70:
2057330f729Sjoerg return CudaVersion::CUDA_70;
2067330f729Sjoerg case 75:
2077330f729Sjoerg return CudaVersion::CUDA_75;
2087330f729Sjoerg case 80:
2097330f729Sjoerg return CudaVersion::CUDA_80;
2107330f729Sjoerg case 90:
2117330f729Sjoerg return CudaVersion::CUDA_90;
2127330f729Sjoerg case 91:
2137330f729Sjoerg return CudaVersion::CUDA_91;
2147330f729Sjoerg case 92:
2157330f729Sjoerg return CudaVersion::CUDA_92;
2167330f729Sjoerg case 100:
2177330f729Sjoerg return CudaVersion::CUDA_100;
2187330f729Sjoerg case 101:
2197330f729Sjoerg return CudaVersion::CUDA_101;
220*e038c9c4Sjoerg case 102:
221*e038c9c4Sjoerg return CudaVersion::CUDA_102;
222*e038c9c4Sjoerg case 110:
223*e038c9c4Sjoerg return CudaVersion::CUDA_110;
224*e038c9c4Sjoerg case 111:
225*e038c9c4Sjoerg return CudaVersion::CUDA_111;
226*e038c9c4Sjoerg case 112:
227*e038c9c4Sjoerg return CudaVersion::CUDA_112;
2287330f729Sjoerg default:
2297330f729Sjoerg return CudaVersion::UNKNOWN;
2307330f729Sjoerg }
2317330f729Sjoerg }
2327330f729Sjoerg
CudaFeatureEnabled(llvm::VersionTuple Version,CudaFeature Feature)2337330f729Sjoerg bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
2347330f729Sjoerg return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
2357330f729Sjoerg }
2367330f729Sjoerg
CudaFeatureEnabled(CudaVersion Version,CudaFeature Feature)2377330f729Sjoerg bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
2387330f729Sjoerg switch (Feature) {
2397330f729Sjoerg case CudaFeature::CUDA_USES_NEW_LAUNCH:
2407330f729Sjoerg return Version >= CudaVersion::CUDA_92;
2417330f729Sjoerg case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
2427330f729Sjoerg return Version >= CudaVersion::CUDA_101;
2437330f729Sjoerg }
2447330f729Sjoerg llvm_unreachable("Unknown CUDA feature.");
2457330f729Sjoerg }
2467330f729Sjoerg } // namespace clang
247