1 | #include "clang/Basic/Cuda.h" |
2 | |
3 | #include "llvm/ADT/Twine.h" |
4 | #include "llvm/Support/ErrorHandling.h" |
5 | #include "llvm/Support/VersionTuple.h" |
6 | |
7 | namespace clang { |
8 | |
9 | struct CudaVersionMapEntry { |
10 | const char *Name; |
11 | CudaVersion Version; |
12 | llvm::VersionTuple TVersion; |
13 | }; |
14 | #define CUDA_ENTRY(major, minor) \ |
15 | { \ |
16 | #major "." #minor, CudaVersion::CUDA_##major##minor, \ |
17 | llvm::VersionTuple(major, minor) \ |
18 | } |
19 | |
20 | static const CudaVersionMapEntry CudaNameVersionMap[] = { |
21 | CUDA_ENTRY(7, 0), |
22 | CUDA_ENTRY(7, 5), |
23 | CUDA_ENTRY(8, 0), |
24 | CUDA_ENTRY(9, 0), |
25 | CUDA_ENTRY(9, 1), |
26 | CUDA_ENTRY(9, 2), |
27 | CUDA_ENTRY(10, 0), |
28 | CUDA_ENTRY(10, 1), |
29 | CUDA_ENTRY(10, 2), |
30 | CUDA_ENTRY(11, 0), |
31 | CUDA_ENTRY(11, 1), |
32 | CUDA_ENTRY(11, 2), |
33 | CUDA_ENTRY(11, 3), |
34 | CUDA_ENTRY(11, 4), |
35 | CUDA_ENTRY(11, 5), |
36 | CUDA_ENTRY(11, 6), |
37 | CUDA_ENTRY(11, 7), |
38 | CUDA_ENTRY(11, 8), |
39 | CUDA_ENTRY(12, 0), |
40 | CUDA_ENTRY(12, 1), |
41 | CUDA_ENTRY(12, 2), |
42 | CUDA_ENTRY(12, 3), |
43 | CUDA_ENTRY(12, 4), |
44 | CUDA_ENTRY(12, 5), |
45 | CUDA_ENTRY(12, 6), |
46 | CUDA_ENTRY(12, 8), |
47 | {.Name: "" , .Version: CudaVersion::NEW, .TVersion: llvm::VersionTuple(std::numeric_limits<int>::max())}, |
48 | {.Name: "unknown" , .Version: CudaVersion::UNKNOWN, .TVersion: {}} // End of list tombstone. |
49 | }; |
50 | #undef CUDA_ENTRY |
51 | |
52 | const char *CudaVersionToString(CudaVersion V) { |
53 | for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I) |
54 | if (I->Version == V) |
55 | return I->Name; |
56 | |
57 | return CudaVersionToString(V: CudaVersion::UNKNOWN); |
58 | } |
59 | |
60 | CudaVersion CudaStringToVersion(const llvm::Twine &S) { |
61 | std::string VS = S.str(); |
62 | for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I) |
63 | if (I->Name == VS) |
64 | return I->Version; |
65 | return CudaVersion::UNKNOWN; |
66 | } |
67 | |
68 | CudaVersion ToCudaVersion(llvm::VersionTuple Version) { |
69 | for (auto *I = CudaNameVersionMap; I->Version != CudaVersion::UNKNOWN; ++I) |
70 | if (I->TVersion == Version) |
71 | return I->Version; |
72 | return CudaVersion::UNKNOWN; |
73 | } |
74 | |
75 | CudaVersion MinVersionForOffloadArch(OffloadArch A) { |
76 | if (A == OffloadArch::UNKNOWN) |
77 | return CudaVersion::UNKNOWN; |
78 | |
79 | // AMD GPUs do not depend on CUDA versions. |
80 | if (IsAMDOffloadArch(A)) |
81 | return CudaVersion::CUDA_70; |
82 | |
83 | switch (A) { |
84 | case OffloadArch::SM_20: |
85 | case OffloadArch::SM_21: |
86 | case OffloadArch::SM_30: |
87 | case OffloadArch::SM_32_: |
88 | case OffloadArch::SM_35: |
89 | case OffloadArch::SM_37: |
90 | case OffloadArch::SM_50: |
91 | case OffloadArch::SM_52: |
92 | case OffloadArch::SM_53: |
93 | return CudaVersion::CUDA_70; |
94 | case OffloadArch::SM_60: |
95 | case OffloadArch::SM_61: |
96 | case OffloadArch::SM_62: |
97 | return CudaVersion::CUDA_80; |
98 | case OffloadArch::SM_70: |
99 | return CudaVersion::CUDA_90; |
100 | case OffloadArch::SM_72: |
101 | return CudaVersion::CUDA_91; |
102 | case OffloadArch::SM_75: |
103 | return CudaVersion::CUDA_100; |
104 | case OffloadArch::SM_80: |
105 | return CudaVersion::CUDA_110; |
106 | case OffloadArch::SM_86: |
107 | return CudaVersion::CUDA_111; |
108 | case OffloadArch::SM_87: |
109 | return CudaVersion::CUDA_114; |
110 | case OffloadArch::SM_89: |
111 | case OffloadArch::SM_90: |
112 | return CudaVersion::CUDA_118; |
113 | case OffloadArch::SM_90a: |
114 | return CudaVersion::CUDA_120; |
115 | case OffloadArch::SM_100: |
116 | case OffloadArch::SM_100a: |
117 | case OffloadArch::SM_101: |
118 | case OffloadArch::SM_101a: |
119 | case OffloadArch::SM_120: |
120 | case OffloadArch::SM_120a: |
121 | return CudaVersion::CUDA_128; |
122 | default: |
123 | llvm_unreachable("invalid enum" ); |
124 | } |
125 | } |
126 | |
127 | CudaVersion MaxVersionForOffloadArch(OffloadArch A) { |
128 | // AMD GPUs do not depend on CUDA versions. |
129 | if (IsAMDOffloadArch(A)) |
130 | return CudaVersion::NEW; |
131 | |
132 | switch (A) { |
133 | case OffloadArch::UNKNOWN: |
134 | return CudaVersion::UNKNOWN; |
135 | case OffloadArch::SM_20: |
136 | case OffloadArch::SM_21: |
137 | return CudaVersion::CUDA_80; |
138 | case OffloadArch::SM_30: |
139 | case OffloadArch::SM_32_: |
140 | return CudaVersion::CUDA_102; |
141 | case OffloadArch::SM_35: |
142 | case OffloadArch::SM_37: |
143 | return CudaVersion::CUDA_118; |
144 | default: |
145 | return CudaVersion::NEW; |
146 | } |
147 | } |
148 | |
149 | bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) { |
150 | return CudaFeatureEnabled(ToCudaVersion(Version), Feature); |
151 | } |
152 | |
153 | bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) { |
154 | switch (Feature) { |
155 | case CudaFeature::CUDA_USES_NEW_LAUNCH: |
156 | return Version >= CudaVersion::CUDA_92; |
157 | case CudaFeature::CUDA_USES_FATBIN_REGISTER_END: |
158 | return Version >= CudaVersion::CUDA_101; |
159 | } |
160 | llvm_unreachable("Unknown CUDA feature." ); |
161 | } |
162 | } // namespace clang |
163 | |