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 } 36 llvm_unreachable("invalid enum"); 37 } 38 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 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 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 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 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 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 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 217 bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) { 218 return CudaFeatureEnabled(ToCudaVersion(Version), Feature); 219 } 220 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