1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H |
14 | #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H |
15 | |
16 | #include "clang/Basic/TargetInfo.h" |
17 | #include "clang/Basic/TargetOptions.h" |
18 | #include "llvm/ADT/StringSet.h" |
19 | #include "llvm/ADT/Triple.h" |
20 | #include "llvm/Support/Compiler.h" |
21 | #include "llvm/Support/TargetParser.h" |
22 | |
23 | namespace clang { |
24 | namespace targets { |
25 | |
26 | class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { |
27 | |
28 | static const Builtin::Info BuiltinInfo[]; |
29 | static const char *const GCCRegNames[]; |
30 | |
31 | enum AddrSpace { |
32 | Generic = 0, |
33 | Global = 1, |
34 | Local = 3, |
35 | Constant = 4, |
36 | Private = 5 |
37 | }; |
38 | static const LangASMap AMDGPUDefIsGenMap; |
39 | static const LangASMap AMDGPUDefIsPrivMap; |
40 | |
41 | llvm::AMDGPU::GPUKind GPUKind; |
42 | unsigned GPUFeatures; |
43 | |
44 | |
45 | bool hasFP64() const { |
46 | return getTriple().getArch() == llvm::Triple::amdgcn || |
47 | !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64); |
48 | } |
49 | |
50 | |
51 | bool hasFastFMAF() const { |
52 | return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32); |
53 | } |
54 | |
55 | |
56 | bool hasFastFMA() const { |
57 | return getTriple().getArch() == llvm::Triple::amdgcn; |
58 | } |
59 | |
60 | bool hasFMAF() const { |
61 | return getTriple().getArch() == llvm::Triple::amdgcn || |
62 | !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA); |
63 | } |
64 | |
65 | bool hasFullRateDenormalsF32() const { |
66 | return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32); |
67 | } |
68 | |
69 | bool hasLDEXPF() const { |
70 | return getTriple().getArch() == llvm::Triple::amdgcn || |
71 | !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP); |
72 | } |
73 | |
74 | static bool isAMDGCN(const llvm::Triple &TT) { |
75 | return TT.getArch() == llvm::Triple::amdgcn; |
76 | } |
77 | |
78 | static bool isR600(const llvm::Triple &TT) { |
79 | return TT.getArch() == llvm::Triple::r600; |
80 | } |
81 | |
82 | public: |
83 | AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); |
84 | |
85 | void setAddressSpaceMap(bool DefaultIsPrivate); |
86 | |
87 | void adjust(LangOptions &Opts) override; |
88 | |
89 | uint64_t getPointerWidthV(unsigned AddrSpace) const override { |
90 | if (isR600(getTriple())) |
91 | return 32; |
92 | |
93 | if (AddrSpace == Private || AddrSpace == Local) |
94 | return 32; |
95 | |
96 | return 64; |
97 | } |
98 | |
99 | uint64_t getPointerAlignV(unsigned AddrSpace) const override { |
100 | return getPointerWidthV(AddrSpace); |
101 | } |
102 | |
103 | uint64_t getMaxPointerWidth() const override { |
104 | return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; |
105 | } |
106 | |
107 | const char *getClobbers() const override { return ""; } |
108 | |
109 | ArrayRef<const char *> getGCCRegNames() const override; |
110 | |
111 | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
112 | return None; |
113 | } |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | bool validateAsmConstraint(const char *&Name, |
124 | TargetInfo::ConstraintInfo &Info) const override { |
125 | static const ::llvm::StringSet<> SpecialRegs({ |
126 | "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma", |
127 | "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo", |
128 | "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi", |
129 | }); |
130 | |
131 | StringRef S(Name); |
132 | bool HasLeftParen = false; |
133 | if (S.front() == '{') { |
134 | HasLeftParen = true; |
135 | S = S.drop_front(); |
136 | } |
137 | if (S.empty()) |
138 | return false; |
139 | if (S.front() != 'v' && S.front() != 's') { |
140 | if (!HasLeftParen) |
141 | return false; |
142 | auto E = S.find('}'); |
143 | if (!SpecialRegs.count(S.substr(0, E))) |
144 | return false; |
145 | S = S.drop_front(E + 1); |
146 | if (!S.empty()) |
147 | return false; |
148 | |
149 | Info.setAllowsRegister(); |
150 | Name = S.data() - 1; |
151 | return true; |
152 | } |
153 | S = S.drop_front(); |
154 | if (!HasLeftParen) { |
155 | if (!S.empty()) |
156 | return false; |
157 | |
158 | Info.setAllowsRegister(); |
159 | Name = S.data() - 1; |
160 | return true; |
161 | } |
162 | bool HasLeftBracket = false; |
163 | if (!S.empty() && S.front() == '[') { |
164 | HasLeftBracket = true; |
165 | S = S.drop_front(); |
166 | } |
167 | unsigned long long N; |
168 | if (S.empty() || consumeUnsignedInteger(S, 10, N)) |
169 | return false; |
170 | if (!S.empty() && S.front() == ':') { |
171 | if (!HasLeftBracket) |
172 | return false; |
173 | S = S.drop_front(); |
174 | unsigned long long M; |
175 | if (consumeUnsignedInteger(S, 10, M) || N >= M) |
176 | return false; |
177 | } |
178 | if (HasLeftBracket) { |
179 | if (S.empty() || S.front() != ']') |
180 | return false; |
181 | S = S.drop_front(); |
182 | } |
183 | if (S.empty() || S.front() != '}') |
184 | return false; |
185 | S = S.drop_front(); |
186 | if (!S.empty()) |
187 | return false; |
188 | |
189 | Info.setAllowsRegister(); |
190 | Name = S.data() - 1; |
191 | return true; |
192 | } |
193 | |
194 | |
195 | |
196 | |
197 | std::string convertConstraint(const char *&Constraint) const override { |
198 | const char *Begin = Constraint; |
199 | TargetInfo::ConstraintInfo Info("", ""); |
200 | if (validateAsmConstraint(Constraint, Info)) |
201 | return std::string(Begin).substr(0, Constraint - Begin + 1); |
202 | |
203 | Constraint = Begin; |
204 | return std::string(1, *Constraint); |
205 | } |
206 | |
207 | bool |
208 | initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
209 | StringRef CPU, |
210 | const std::vector<std::string> &FeatureVec) const override; |
211 | |
212 | void adjustTargetOptions(const CodeGenOptions &CGOpts, |
213 | TargetOptions &TargetOpts) const override; |
214 | |
215 | ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
216 | |
217 | void getTargetDefines(const LangOptions &Opts, |
218 | MacroBuilder &Builder) const override; |
219 | |
220 | BuiltinVaListKind getBuiltinVaListKind() const override { |
221 | return TargetInfo::CharPtrBuiltinVaList; |
222 | } |
223 | |
224 | bool isValidCPUName(StringRef Name) const override { |
225 | if (getTriple().getArch() == llvm::Triple::amdgcn) |
226 | return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE; |
227 | return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE; |
228 | } |
229 | |
230 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
231 | |
232 | bool setCPU(const std::string &Name) override { |
233 | if (getTriple().getArch() == llvm::Triple::amdgcn) { |
234 | GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name); |
235 | GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind); |
236 | } else { |
237 | GPUKind = llvm::AMDGPU::parseArchR600(Name); |
238 | GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind); |
239 | } |
240 | |
241 | return GPUKind != llvm::AMDGPU::GK_NONE; |
242 | } |
243 | |
244 | void setSupportedOpenCLOpts() override { |
245 | auto &Opts = getSupportedOpenCLOpts(); |
246 | Opts.support("cl_clang_storage_class_specifiers"); |
247 | Opts.support("cl_khr_icd"); |
248 | |
249 | bool IsAMDGCN = isAMDGCN(getTriple()); |
250 | |
251 | if (hasFP64()) |
252 | Opts.support("cl_khr_fp64"); |
253 | |
254 | if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) { |
255 | Opts.support("cl_khr_byte_addressable_store"); |
256 | Opts.support("cl_khr_global_int32_base_atomics"); |
257 | Opts.support("cl_khr_global_int32_extended_atomics"); |
258 | Opts.support("cl_khr_local_int32_base_atomics"); |
259 | Opts.support("cl_khr_local_int32_extended_atomics"); |
260 | } |
261 | |
262 | if (IsAMDGCN) { |
263 | Opts.support("cl_khr_fp16"); |
264 | Opts.support("cl_khr_int64_base_atomics"); |
265 | Opts.support("cl_khr_int64_extended_atomics"); |
266 | Opts.support("cl_khr_mipmap_image"); |
267 | Opts.support("cl_khr_subgroups"); |
268 | Opts.support("cl_khr_3d_image_writes"); |
269 | Opts.support("cl_amd_media_ops"); |
270 | Opts.support("cl_amd_media_ops2"); |
271 | } |
272 | } |
273 | |
274 | LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override { |
275 | switch (TK) { |
276 | case OCLTK_Image: |
277 | return LangAS::opencl_constant; |
278 | |
279 | case OCLTK_ClkEvent: |
280 | case OCLTK_Queue: |
281 | case OCLTK_ReserveID: |
282 | return LangAS::opencl_global; |
283 | |
284 | default: |
285 | return TargetInfo::getOpenCLTypeAddrSpace(TK); |
286 | } |
287 | } |
288 | |
289 | LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override { |
290 | switch (AS) { |
291 | case 0: |
292 | return LangAS::opencl_generic; |
293 | case 1: |
294 | return LangAS::opencl_global; |
295 | case 3: |
296 | return LangAS::opencl_local; |
297 | case 4: |
298 | return LangAS::opencl_constant; |
299 | case 5: |
300 | return LangAS::opencl_private; |
301 | default: |
302 | return getLangASFromTargetAS(AS); |
303 | } |
304 | } |
305 | |
306 | LangAS getCUDABuiltinAddressSpace(unsigned AS) const override { |
307 | return LangAS::Default; |
308 | } |
309 | |
310 | llvm::Optional<LangAS> getConstantAddressSpace() const override { |
311 | return getLangASFromTargetAS(Constant); |
312 | } |
313 | |
314 | |
315 | unsigned getVtblPtrAddressSpace() const override { |
316 | return static_cast<unsigned>(Constant); |
317 | } |
318 | |
319 | |
320 | |
321 | |
322 | |
323 | |
324 | |
325 | Optional<unsigned> |
326 | getDWARFAddressSpace(unsigned AddressSpace) const override { |
327 | const unsigned DWARF_Private = 1; |
328 | const unsigned DWARF_Local = 2; |
329 | if (AddressSpace == Private) { |
330 | return DWARF_Private; |
331 | } else if (AddressSpace == Local) { |
332 | return DWARF_Local; |
333 | } else { |
334 | return None; |
335 | } |
336 | } |
337 | |
338 | CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { |
339 | switch (CC) { |
340 | default: |
341 | return CCCR_Warning; |
342 | case CC_C: |
343 | case CC_OpenCLKernel: |
344 | return CCCR_OK; |
345 | } |
346 | } |
347 | |
348 | |
349 | |
350 | |
351 | uint64_t getNullPointerValue(LangAS AS) const override { |
352 | return AS == LangAS::opencl_local ? ~0 : 0; |
353 | } |
354 | |
355 | void setAuxTarget(const TargetInfo *Aux) override; |
356 | }; |
357 | |
358 | } |
359 | } |
360 | |
361 | #endif |
362 | |