Cuda.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "clang/Basic/Cuda.h"
  2. #include "llvm/ADT/StringRef.h"
  3. #include "llvm/ADT/Twine.h"
  4. #include "llvm/Support/ErrorHandling.h"
  5. #include "llvm/Support/VersionTuple.h"
  6. namespace clang {
  7. struct CudaVersionMapEntry {
  8. const char *Name;
  9. CudaVersion Version;
  10. llvm::VersionTuple TVersion;
  11. };
  12. #define CUDA_ENTRY(major, minor) \
  13. { \
  14. #major "." #minor, CudaVersion::CUDA_##major##minor, \
  15. llvm::VersionTuple(major, minor) \
  16. }
  17. static const CudaVersionMapEntry CudaNameVersionMap[] = {
  18. CUDA_ENTRY(7, 0),
  19. CUDA_ENTRY(7, 5),
  20. CUDA_ENTRY(8, 0),
  21. CUDA_ENTRY(9, 0),
  22. CUDA_ENTRY(9, 1),
  23. CUDA_ENTRY(9, 2),
  24. CUDA_ENTRY(10, 0),
  25. CUDA_ENTRY(10, 1),
  26. CUDA_ENTRY(10, 2),
  27. CUDA_ENTRY(11, 0),
  28. CUDA_ENTRY(11, 1),
  29. CUDA_ENTRY(11, 2),
  30. CUDA_ENTRY(11, 3),
  31. CUDA_ENTRY(11, 4),
  32. CUDA_ENTRY(11, 5),
  33. CUDA_ENTRY(11, 6),
  34. CUDA_ENTRY(11, 7),
  35. CUDA_ENTRY(11, 8),
  36. {"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
  37. {"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
  38. };
  39. #undef CUDA_ENTRY
  40. const char *CudaVersionToString(CudaVersion V) {
  41. for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
  42. if (I->Version == V)
  43. return I->Name;
  44. return CudaVersionToString(CudaVersion::UNKNOWN);
  45. }
  46. CudaVersion CudaStringToVersion(const llvm::Twine &S) {
  47. std::string VS = S.str();
  48. for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
  49. if (I->Name == VS)
  50. return I->Version;
  51. return CudaVersion::UNKNOWN;
  52. }
  53. CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
  54. for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I)
  55. if (I->TVersion == Version)
  56. return I->Version;
  57. return CudaVersion::UNKNOWN;
  58. }
  59. namespace {
  60. struct CudaArchToStringMap {
  61. CudaArch arch;
  62. const char *arch_name;
  63. const char *virtual_arch_name;
  64. };
  65. } // namespace
  66. #define SM2(sm, ca) \
  67. { CudaArch::SM_##sm, "sm_" #sm, ca }
  68. #define SM(sm) SM2(sm, "compute_" #sm)
  69. #define GFX(gpu) \
  70. { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
  71. static const CudaArchToStringMap arch_names[] = {
  72. // clang-format off
  73. {CudaArch::UNUSED, "", ""},
  74. SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
  75. SM(30), SM(32), SM(35), SM(37), // Kepler
  76. SM(50), SM(52), SM(53), // Maxwell
  77. SM(60), SM(61), SM(62), // Pascal
  78. SM(70), SM(72), // Volta
  79. SM(75), // Turing
  80. SM(80), SM(86), // Ampere
  81. SM(87), // Jetson/Drive AGX Orin
  82. SM(89), // Ada Lovelace
  83. SM(90), // Hopper
  84. GFX(600), // gfx600
  85. GFX(601), // gfx601
  86. GFX(602), // gfx602
  87. GFX(700), // gfx700
  88. GFX(701), // gfx701
  89. GFX(702), // gfx702
  90. GFX(703), // gfx703
  91. GFX(704), // gfx704
  92. GFX(705), // gfx705
  93. GFX(801), // gfx801
  94. GFX(802), // gfx802
  95. GFX(803), // gfx803
  96. GFX(805), // gfx805
  97. GFX(810), // gfx810
  98. GFX(900), // gfx900
  99. GFX(902), // gfx902
  100. GFX(904), // gfx903
  101. GFX(906), // gfx906
  102. GFX(908), // gfx908
  103. GFX(909), // gfx909
  104. GFX(90a), // gfx90a
  105. GFX(90c), // gfx90c
  106. GFX(940), // gfx940
  107. GFX(1010), // gfx1010
  108. GFX(1011), // gfx1011
  109. GFX(1012), // gfx1012
  110. GFX(1013), // gfx1013
  111. GFX(1030), // gfx1030
  112. GFX(1031), // gfx1031
  113. GFX(1032), // gfx1032
  114. GFX(1033), // gfx1033
  115. GFX(1034), // gfx1034
  116. GFX(1035), // gfx1035
  117. GFX(1036), // gfx1036
  118. GFX(1100), // gfx1100
  119. GFX(1101), // gfx1101
  120. GFX(1102), // gfx1102
  121. GFX(1103), // gfx1103
  122. {CudaArch::Generic, "generic", ""},
  123. // clang-format on
  124. };
  125. #undef SM
  126. #undef SM2
  127. #undef GFX
  128. const char *CudaArchToString(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->arch_name;
  135. }
  136. const char *CudaArchToVirtualArchString(CudaArch A) {
  137. auto result = std::find_if(
  138. std::begin(arch_names), std::end(arch_names),
  139. [A](const CudaArchToStringMap &map) { return A == map.arch; });
  140. if (result == std::end(arch_names))
  141. return "unknown";
  142. return result->virtual_arch_name;
  143. }
  144. CudaArch StringToCudaArch(llvm::StringRef S) {
  145. auto result = std::find_if(
  146. std::begin(arch_names), std::end(arch_names),
  147. [S](const CudaArchToStringMap &map) { return S == map.arch_name; });
  148. if (result == std::end(arch_names))
  149. return CudaArch::UNKNOWN;
  150. return result->arch;
  151. }
  152. CudaVersion MinVersionForCudaArch(CudaArch A) {
  153. if (A == CudaArch::UNKNOWN)
  154. return CudaVersion::UNKNOWN;
  155. // AMD GPUs do not depend on CUDA versions.
  156. if (IsAMDGpuArch(A))
  157. return CudaVersion::CUDA_70;
  158. switch (A) {
  159. case CudaArch::SM_20:
  160. case CudaArch::SM_21:
  161. case CudaArch::SM_30:
  162. case CudaArch::SM_32:
  163. case CudaArch::SM_35:
  164. case CudaArch::SM_37:
  165. case CudaArch::SM_50:
  166. case CudaArch::SM_52:
  167. case CudaArch::SM_53:
  168. return CudaVersion::CUDA_70;
  169. case CudaArch::SM_60:
  170. case CudaArch::SM_61:
  171. case CudaArch::SM_62:
  172. return CudaVersion::CUDA_80;
  173. case CudaArch::SM_70:
  174. return CudaVersion::CUDA_90;
  175. case CudaArch::SM_72:
  176. return CudaVersion::CUDA_91;
  177. case CudaArch::SM_75:
  178. return CudaVersion::CUDA_100;
  179. case CudaArch::SM_80:
  180. return CudaVersion::CUDA_110;
  181. case CudaArch::SM_86:
  182. return CudaVersion::CUDA_111;
  183. case CudaArch::SM_87:
  184. return CudaVersion::CUDA_114;
  185. case CudaArch::SM_89:
  186. case CudaArch::SM_90:
  187. return CudaVersion::CUDA_118;
  188. default:
  189. llvm_unreachable("invalid enum");
  190. }
  191. }
  192. CudaVersion MaxVersionForCudaArch(CudaArch A) {
  193. // AMD GPUs do not depend on CUDA versions.
  194. if (IsAMDGpuArch(A))
  195. return CudaVersion::NEW;
  196. switch (A) {
  197. case CudaArch::UNKNOWN:
  198. return CudaVersion::UNKNOWN;
  199. case CudaArch::SM_20:
  200. case CudaArch::SM_21:
  201. return CudaVersion::CUDA_80;
  202. case CudaArch::SM_30:
  203. return CudaVersion::CUDA_110;
  204. default:
  205. return CudaVersion::NEW;
  206. }
  207. }
  208. bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
  209. return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
  210. }
  211. bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
  212. switch (Feature) {
  213. case CudaFeature::CUDA_USES_NEW_LAUNCH:
  214. return Version >= CudaVersion::CUDA_92;
  215. case CudaFeature::CUDA_USES_FATBIN_REGISTER_END:
  216. return Version >= CudaVersion::CUDA_101;
  217. }
  218. llvm_unreachable("Unknown CUDA feature.");
  219. }
  220. } // namespace clang