Home | History | Annotate | Line # | Download | only in Basic
      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(1030), // gfx1030
    109     GFX(1031), // gfx1031
    110     GFX(1032), // gfx1032
    111     GFX(1033), // gfx1033
    112     GFX(1034), // gfx1034
    113     // clang-format on
    114 };
    115 #undef SM
    116 #undef SM2
    117 #undef GFX
    118 
    119 const char *CudaArchToString(CudaArch A) {
    120   auto result = std::find_if(
    121       std::begin(arch_names), std::end(arch_names),
    122       [A](const CudaArchToStringMap &map) { return A == map.arch; });
    123   if (result == std::end(arch_names))
    124     return "unknown";
    125   return result->arch_name;
    126 }
    127 
    128 const char *CudaArchToVirtualArchString(CudaArch A) {
    129   auto result = std::find_if(
    130       std::begin(arch_names), std::end(arch_names),
    131       [A](const CudaArchToStringMap &map) { return A == map.arch; });
    132   if (result == std::end(arch_names))
    133     return "unknown";
    134   return result->virtual_arch_name;
    135 }
    136 
    137 CudaArch StringToCudaArch(llvm::StringRef S) {
    138   auto result = std::find_if(
    139       std::begin(arch_names), std::end(arch_names),
    140       [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
    141   if (result == std::end(arch_names))
    142     return CudaArch::UNKNOWN;
    143   return result->arch;
    144 }
    145 
    146 CudaVersion MinVersionForCudaArch(CudaArch A) {
    147   if (A == CudaArch::UNKNOWN)
    148     return CudaVersion::UNKNOWN;
    149 
    150   // AMD GPUs do not depend on CUDA versions.
    151   if (IsAMDGpuArch(A))
    152     return CudaVersion::CUDA_70;
    153 
    154   switch (A) {
    155   case CudaArch::SM_20:
    156   case CudaArch::SM_21:
    157   case CudaArch::SM_30:
    158   case CudaArch::SM_32:
    159   case CudaArch::SM_35:
    160   case CudaArch::SM_37:
    161   case CudaArch::SM_50:
    162   case CudaArch::SM_52:
    163   case CudaArch::SM_53:
    164     return CudaVersion::CUDA_70;
    165   case CudaArch::SM_60:
    166   case CudaArch::SM_61:
    167   case CudaArch::SM_62:
    168     return CudaVersion::CUDA_80;
    169   case CudaArch::SM_70:
    170     return CudaVersion::CUDA_90;
    171   case CudaArch::SM_72:
    172     return CudaVersion::CUDA_91;
    173   case CudaArch::SM_75:
    174     return CudaVersion::CUDA_100;
    175   case CudaArch::SM_80:
    176     return CudaVersion::CUDA_110;
    177   case CudaArch::SM_86:
    178     return CudaVersion::CUDA_111;
    179   default:
    180     llvm_unreachable("invalid enum");
    181   }
    182 }
    183 
    184 CudaVersion MaxVersionForCudaArch(CudaArch A) {
    185   // AMD GPUs do not depend on CUDA versions.
    186   if (IsAMDGpuArch(A))
    187     return CudaVersion::LATEST;
    188 
    189   switch (A) {
    190   case CudaArch::UNKNOWN:
    191     return CudaVersion::UNKNOWN;
    192   case CudaArch::SM_20:
    193   case CudaArch::SM_21:
    194     return CudaVersion::CUDA_80;
    195   default:
    196     return CudaVersion::LATEST;
    197   }
    198 }
    199 
    200 CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
    201   int IVer =
    202       Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
    203   switch(IVer) {
    204   case 70:
    205     return CudaVersion::CUDA_70;
    206   case 75:
    207     return CudaVersion::CUDA_75;
    208   case 80:
    209     return CudaVersion::CUDA_80;
    210   case 90:
    211     return CudaVersion::CUDA_90;
    212   case 91:
    213     return CudaVersion::CUDA_91;
    214   case 92:
    215     return CudaVersion::CUDA_92;
    216   case 100:
    217     return CudaVersion::CUDA_100;
    218   case 101:
    219     return CudaVersion::CUDA_101;
    220   case 102:
    221     return CudaVersion::CUDA_102;
    222   case 110:
    223     return CudaVersion::CUDA_110;
    224   case 111:
    225     return CudaVersion::CUDA_111;
    226   case 112:
    227     return CudaVersion::CUDA_112;
    228   default:
    229     return CudaVersion::UNKNOWN;
    230   }
    231 }
    232 
    233 bool CudaFeatureEnabled(llvm::VersionTuple  Version, CudaFeature Feature) {
    234   return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
    235 }
    236 
    237 bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
    238   switch (Feature) {
    239   case CudaFeature::CUDA_USES_NEW_LAUNCH:
    240     return Version >= CudaVersion::CUDA_92;
    241   case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
    242     return Version >= CudaVersion::CUDA_101;
    243   }
    244   llvm_unreachable("Unknown CUDA feature.");
    245 }
    246 } // namespace clang
    247