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 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 case CudaVersion::CUDA_111: 36 return "11.1"; 37 case CudaVersion::CUDA_112: 38 return "11.2"; 39 case CudaVersion::CUDA_113: 40 return "11.3"; 41 case CudaVersion::CUDA_114: 42 return "11.4"; 43 case CudaVersion::NEW: 44 return ""; 45 } 46 llvm_unreachable("invalid enum"); 47 } 48 49 CudaVersion CudaStringToVersion(const llvm::Twine &S) { 50 return llvm::StringSwitch<CudaVersion>(S.str()) 51 .Case("7.0", CudaVersion::CUDA_70) 52 .Case("7.5", CudaVersion::CUDA_75) 53 .Case("8.0", CudaVersion::CUDA_80) 54 .Case("9.0", CudaVersion::CUDA_90) 55 .Case("9.1", CudaVersion::CUDA_91) 56 .Case("9.2", CudaVersion::CUDA_92) 57 .Case("10.0", CudaVersion::CUDA_100) 58 .Case("10.1", CudaVersion::CUDA_101) 59 .Case("10.2", CudaVersion::CUDA_102) 60 .Case("11.0", CudaVersion::CUDA_110) 61 .Case("11.1", CudaVersion::CUDA_111) 62 .Case("11.2", CudaVersion::CUDA_112) 63 .Case("11.3", CudaVersion::CUDA_113) 64 .Case("11.4", CudaVersion::CUDA_114) 65 .Default(CudaVersion::UNKNOWN); 66 } 67 68 namespace { 69 struct CudaArchToStringMap { 70 CudaArch arch; 71 const char *arch_name; 72 const char *virtual_arch_name; 73 }; 74 } // namespace 75 76 #define SM2(sm, ca) \ 77 { CudaArch::SM_##sm, "sm_" #sm, ca } 78 #define SM(sm) SM2(sm, "compute_" #sm) 79 #define GFX(gpu) \ 80 { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" } 81 static const CudaArchToStringMap arch_names[] = { 82 // clang-format off 83 {CudaArch::UNUSED, "", ""}, 84 SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi 85 SM(30), SM(32), SM(35), SM(37), // Kepler 86 SM(50), SM(52), SM(53), // Maxwell 87 SM(60), SM(61), SM(62), // Pascal 88 SM(70), SM(72), // Volta 89 SM(75), // Turing 90 SM(80), SM(86), // Ampere 91 GFX(600), // gfx600 92 GFX(601), // gfx601 93 GFX(602), // gfx602 94 GFX(700), // gfx700 95 GFX(701), // gfx701 96 GFX(702), // gfx702 97 GFX(703), // gfx703 98 GFX(704), // gfx704 99 GFX(705), // gfx705 100 GFX(801), // gfx801 101 GFX(802), // gfx802 102 GFX(803), // gfx803 103 GFX(805), // gfx805 104 GFX(810), // gfx810 105 GFX(900), // gfx900 106 GFX(902), // gfx902 107 GFX(904), // gfx903 108 GFX(906), // gfx906 109 GFX(908), // gfx908 110 GFX(909), // gfx909 111 GFX(90a), // gfx90a 112 GFX(90c), // gfx90c 113 GFX(1010), // gfx1010 114 GFX(1011), // gfx1011 115 GFX(1012), // gfx1012 116 GFX(1013), // gfx1013 117 GFX(1030), // gfx1030 118 GFX(1031), // gfx1031 119 GFX(1032), // gfx1032 120 GFX(1033), // gfx1033 121 GFX(1034), // gfx1034 122 GFX(1035), // gfx1035 123 // clang-format on 124 }; 125 #undef SM 126 #undef SM2 127 #undef GFX 128 129 const char *CudaArchToString(CudaArch A) { 130 auto result = std::find_if( 131 std::begin(arch_names), std::end(arch_names), 132 [A](const CudaArchToStringMap &map) { return A == map.arch; }); 133 if (result == std::end(arch_names)) 134 return "unknown"; 135 return result->arch_name; 136 } 137 138 const char *CudaArchToVirtualArchString(CudaArch A) { 139 auto result = std::find_if( 140 std::begin(arch_names), std::end(arch_names), 141 [A](const CudaArchToStringMap &map) { return A == map.arch; }); 142 if (result == std::end(arch_names)) 143 return "unknown"; 144 return result->virtual_arch_name; 145 } 146 147 CudaArch StringToCudaArch(llvm::StringRef S) { 148 auto result = std::find_if( 149 std::begin(arch_names), std::end(arch_names), 150 [S](const CudaArchToStringMap &map) { return S == map.arch_name; }); 151 if (result == std::end(arch_names)) 152 return CudaArch::UNKNOWN; 153 return result->arch; 154 } 155 156 CudaVersion MinVersionForCudaArch(CudaArch A) { 157 if (A == CudaArch::UNKNOWN) 158 return CudaVersion::UNKNOWN; 159 160 // AMD GPUs do not depend on CUDA versions. 161 if (IsAMDGpuArch(A)) 162 return CudaVersion::CUDA_70; 163 164 switch (A) { 165 case CudaArch::SM_20: 166 case CudaArch::SM_21: 167 case CudaArch::SM_30: 168 case CudaArch::SM_32: 169 case CudaArch::SM_35: 170 case CudaArch::SM_37: 171 case CudaArch::SM_50: 172 case CudaArch::SM_52: 173 case CudaArch::SM_53: 174 return CudaVersion::CUDA_70; 175 case CudaArch::SM_60: 176 case CudaArch::SM_61: 177 case CudaArch::SM_62: 178 return CudaVersion::CUDA_80; 179 case CudaArch::SM_70: 180 return CudaVersion::CUDA_90; 181 case CudaArch::SM_72: 182 return CudaVersion::CUDA_91; 183 case CudaArch::SM_75: 184 return CudaVersion::CUDA_100; 185 case CudaArch::SM_80: 186 return CudaVersion::CUDA_110; 187 case CudaArch::SM_86: 188 return CudaVersion::CUDA_111; 189 default: 190 llvm_unreachable("invalid enum"); 191 } 192 } 193 194 CudaVersion MaxVersionForCudaArch(CudaArch A) { 195 // AMD GPUs do not depend on CUDA versions. 196 if (IsAMDGpuArch(A)) 197 return CudaVersion::NEW; 198 199 switch (A) { 200 case CudaArch::UNKNOWN: 201 return CudaVersion::UNKNOWN; 202 case CudaArch::SM_20: 203 case CudaArch::SM_21: 204 return CudaVersion::CUDA_80; 205 case CudaArch::SM_30: 206 return CudaVersion::CUDA_110; 207 default: 208 return CudaVersion::NEW; 209 } 210 } 211 212 CudaVersion ToCudaVersion(llvm::VersionTuple Version) { 213 int IVer = 214 Version.getMajor() * 10 + Version.getMinor().getValueOr(0); 215 switch(IVer) { 216 case 70: 217 return CudaVersion::CUDA_70; 218 case 75: 219 return CudaVersion::CUDA_75; 220 case 80: 221 return CudaVersion::CUDA_80; 222 case 90: 223 return CudaVersion::CUDA_90; 224 case 91: 225 return CudaVersion::CUDA_91; 226 case 92: 227 return CudaVersion::CUDA_92; 228 case 100: 229 return CudaVersion::CUDA_100; 230 case 101: 231 return CudaVersion::CUDA_101; 232 case 102: 233 return CudaVersion::CUDA_102; 234 case 110: 235 return CudaVersion::CUDA_110; 236 case 111: 237 return CudaVersion::CUDA_111; 238 case 112: 239 return CudaVersion::CUDA_112; 240 case 113: 241 return CudaVersion::CUDA_113; 242 case 114: 243 return CudaVersion::CUDA_114; 244 default: 245 return CudaVersion::UNKNOWN; 246 } 247 } 248 249 bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) { 250 return CudaFeatureEnabled(ToCudaVersion(Version), Feature); 251 } 252 253 bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) { 254 switch (Feature) { 255 case CudaFeature::CUDA_USES_NEW_LAUNCH: 256 return Version >= CudaVersion::CUDA_92; 257 case CudaFeature::CUDA_USES_FATBIN_REGISTER_END: 258 return Version >= CudaVersion::CUDA_101; 259 } 260 llvm_unreachable("Unknown CUDA feature."); 261 } 262 } // namespace clang 263