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