[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / Basic / Targets / AMDGPU.h
blob300d9691d8a0f2207ebc6eb64bd5626c12e55a17
1 //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares AMDGPU TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
14 #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
16 #include "clang/Basic/TargetID.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/TargetOptions.h"
19 #include "llvm/ADT/StringSet.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/TargetParser/TargetParser.h"
22 #include "llvm/TargetParser/Triple.h"
23 #include <optional>
25 namespace clang {
26 namespace targets {
28 class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
30 static const char *const GCCRegNames[];
32 enum AddrSpace {
33 Generic = 0,
34 Global = 1,
35 Local = 3,
36 Constant = 4,
37 Private = 5
39 static const LangASMap AMDGPUDefIsGenMap;
40 static const LangASMap AMDGPUDefIsPrivMap;
42 llvm::AMDGPU::GPUKind GPUKind;
43 unsigned GPUFeatures;
44 unsigned WavefrontSize;
46 /// Whether to use cumode or WGP mode. True for cumode. False for WGP mode.
47 bool CUMode;
49 /// Whether having image instructions.
50 bool HasImage = false;
52 /// Target ID is device name followed by optional feature name postfixed
53 /// by plus or minus sign delimitted by colon, e.g. gfx908:xnack+:sramecc-.
54 /// If the target ID contains feature+, map it to true.
55 /// If the target ID contains feature-, map it to false.
56 /// If the target ID does not contain a feature (default), do not map it.
57 llvm::StringMap<bool> OffloadArchFeatures;
58 std::string TargetID;
60 bool hasFP64() const {
61 return getTriple().getArch() == llvm::Triple::amdgcn ||
62 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64);
65 /// Has fast fma f32
66 bool hasFastFMAF() const {
67 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
70 /// Has fast fma f64
71 bool hasFastFMA() const {
72 return getTriple().getArch() == llvm::Triple::amdgcn;
75 bool hasFMAF() const {
76 return getTriple().getArch() == llvm::Triple::amdgcn ||
77 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA);
80 bool hasFullRateDenormalsF32() const {
81 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
84 bool hasLDEXPF() const {
85 return getTriple().getArch() == llvm::Triple::amdgcn ||
86 !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP);
89 static bool isAMDGCN(const llvm::Triple &TT) {
90 return TT.getArch() == llvm::Triple::amdgcn;
93 static bool isR600(const llvm::Triple &TT) {
94 return TT.getArch() == llvm::Triple::r600;
97 public:
98 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
100 void setAddressSpaceMap(bool DefaultIsPrivate);
102 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
104 uint64_t getPointerWidthV(LangAS AS) const override {
105 if (isR600(getTriple()))
106 return 32;
107 unsigned TargetAS = getTargetAddressSpace(AS);
109 if (TargetAS == Private || TargetAS == Local)
110 return 32;
112 return 64;
115 uint64_t getPointerAlignV(LangAS AddrSpace) const override {
116 return getPointerWidthV(AddrSpace);
119 uint64_t getMaxPointerWidth() const override {
120 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
123 bool hasBFloat16Type() const override { return isAMDGCN(getTriple()); }
125 std::string_view getClobbers() const override { return ""; }
127 ArrayRef<const char *> getGCCRegNames() const override;
129 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
130 return std::nullopt;
133 /// Accepted register names: (n, m is unsigned integer, n < m)
134 /// v
135 /// s
136 /// a
137 /// {vn}, {v[n]}
138 /// {sn}, {s[n]}
139 /// {an}, {a[n]}
140 /// {S} , where S is a special register name
141 ////{v[n:m]}
142 /// {s[n:m]}
143 /// {a[n:m]}
144 bool validateAsmConstraint(const char *&Name,
145 TargetInfo::ConstraintInfo &Info) const override {
146 static const ::llvm::StringSet<> SpecialRegs({
147 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
148 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
149 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
152 switch (*Name) {
153 case 'I':
154 Info.setRequiresImmediate(-16, 64);
155 return true;
156 case 'J':
157 Info.setRequiresImmediate(-32768, 32767);
158 return true;
159 case 'A':
160 case 'B':
161 case 'C':
162 Info.setRequiresImmediate();
163 return true;
164 default:
165 break;
168 StringRef S(Name);
170 if (S == "DA" || S == "DB") {
171 Name++;
172 Info.setRequiresImmediate();
173 return true;
176 bool HasLeftParen = false;
177 if (S.front() == '{') {
178 HasLeftParen = true;
179 S = S.drop_front();
181 if (S.empty())
182 return false;
183 if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
184 if (!HasLeftParen)
185 return false;
186 auto E = S.find('}');
187 if (!SpecialRegs.count(S.substr(0, E)))
188 return false;
189 S = S.drop_front(E + 1);
190 if (!S.empty())
191 return false;
192 // Found {S} where S is a special register.
193 Info.setAllowsRegister();
194 Name = S.data() - 1;
195 return true;
197 S = S.drop_front();
198 if (!HasLeftParen) {
199 if (!S.empty())
200 return false;
201 // Found s, v or a.
202 Info.setAllowsRegister();
203 Name = S.data() - 1;
204 return true;
206 bool HasLeftBracket = false;
207 if (!S.empty() && S.front() == '[') {
208 HasLeftBracket = true;
209 S = S.drop_front();
211 unsigned long long N;
212 if (S.empty() || consumeUnsignedInteger(S, 10, N))
213 return false;
214 if (!S.empty() && S.front() == ':') {
215 if (!HasLeftBracket)
216 return false;
217 S = S.drop_front();
218 unsigned long long M;
219 if (consumeUnsignedInteger(S, 10, M) || N >= M)
220 return false;
222 if (HasLeftBracket) {
223 if (S.empty() || S.front() != ']')
224 return false;
225 S = S.drop_front();
227 if (S.empty() || S.front() != '}')
228 return false;
229 S = S.drop_front();
230 if (!S.empty())
231 return false;
232 // Found {vn}, {sn}, {an}, {v[n]}, {s[n]}, {a[n]}, {v[n:m]}, {s[n:m]}
233 // or {a[n:m]}.
234 Info.setAllowsRegister();
235 Name = S.data() - 1;
236 return true;
239 // \p Constraint will be left pointing at the last character of
240 // the constraint. In practice, it won't be changed unless the
241 // constraint is longer than one character.
242 std::string convertConstraint(const char *&Constraint) const override {
244 StringRef S(Constraint);
245 if (S == "DA" || S == "DB") {
246 return std::string("^") + std::string(Constraint++, 2);
249 const char *Begin = Constraint;
250 TargetInfo::ConstraintInfo Info("", "");
251 if (validateAsmConstraint(Constraint, Info))
252 return std::string(Begin).substr(0, Constraint - Begin + 1);
254 Constraint = Begin;
255 return std::string(1, *Constraint);
258 bool
259 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
260 StringRef CPU,
261 const std::vector<std::string> &FeatureVec) const override;
263 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
265 bool useFP16ConversionIntrinsics() const override { return false; }
267 void getTargetDefines(const LangOptions &Opts,
268 MacroBuilder &Builder) const override;
270 BuiltinVaListKind getBuiltinVaListKind() const override {
271 return TargetInfo::CharPtrBuiltinVaList;
274 bool isValidCPUName(StringRef Name) const override {
275 if (getTriple().getArch() == llvm::Triple::amdgcn)
276 return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
277 return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
280 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
282 bool setCPU(const std::string &Name) override {
283 if (getTriple().getArch() == llvm::Triple::amdgcn) {
284 GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
285 GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
286 } else {
287 GPUKind = llvm::AMDGPU::parseArchR600(Name);
288 GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
291 return GPUKind != llvm::AMDGPU::GK_NONE;
294 void setSupportedOpenCLOpts() override {
295 auto &Opts = getSupportedOpenCLOpts();
296 Opts["cl_clang_storage_class_specifiers"] = true;
297 Opts["__cl_clang_variadic_functions"] = true;
298 Opts["__cl_clang_function_pointers"] = true;
299 Opts["__cl_clang_non_portable_kernel_param_types"] = true;
300 Opts["__cl_clang_bitfields"] = true;
302 bool IsAMDGCN = isAMDGCN(getTriple());
304 Opts["cl_khr_fp64"] = hasFP64();
305 Opts["__opencl_c_fp64"] = hasFP64();
307 if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
308 Opts["cl_khr_byte_addressable_store"] = true;
309 Opts["cl_khr_global_int32_base_atomics"] = true;
310 Opts["cl_khr_global_int32_extended_atomics"] = true;
311 Opts["cl_khr_local_int32_base_atomics"] = true;
312 Opts["cl_khr_local_int32_extended_atomics"] = true;
315 if (IsAMDGCN) {
316 Opts["cl_khr_fp16"] = true;
317 Opts["cl_khr_int64_base_atomics"] = true;
318 Opts["cl_khr_int64_extended_atomics"] = true;
319 Opts["cl_khr_mipmap_image"] = true;
320 Opts["cl_khr_mipmap_image_writes"] = true;
321 Opts["cl_khr_subgroups"] = true;
322 Opts["cl_amd_media_ops"] = true;
323 Opts["cl_amd_media_ops2"] = true;
325 Opts["__opencl_c_images"] = true;
326 Opts["__opencl_c_3d_image_writes"] = true;
327 Opts["cl_khr_3d_image_writes"] = true;
331 LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
332 switch (TK) {
333 case OCLTK_Image:
334 return LangAS::opencl_constant;
336 case OCLTK_ClkEvent:
337 case OCLTK_Queue:
338 case OCLTK_ReserveID:
339 return LangAS::opencl_global;
341 default:
342 return TargetInfo::getOpenCLTypeAddrSpace(TK);
346 LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
347 switch (AS) {
348 case 0:
349 return LangAS::opencl_generic;
350 case 1:
351 return LangAS::opencl_global;
352 case 3:
353 return LangAS::opencl_local;
354 case 4:
355 return LangAS::opencl_constant;
356 case 5:
357 return LangAS::opencl_private;
358 default:
359 return getLangASFromTargetAS(AS);
363 LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
364 switch (AS) {
365 case 0:
366 return LangAS::Default;
367 case 1:
368 return LangAS::cuda_device;
369 case 3:
370 return LangAS::cuda_shared;
371 case 4:
372 return LangAS::cuda_constant;
373 default:
374 return getLangASFromTargetAS(AS);
378 std::optional<LangAS> getConstantAddressSpace() const override {
379 return getLangASFromTargetAS(Constant);
382 const llvm::omp::GV &getGridValue() const override {
383 switch (WavefrontSize) {
384 case 32:
385 return llvm::omp::getAMDGPUGridValues<32>();
386 case 64:
387 return llvm::omp::getAMDGPUGridValues<64>();
388 default:
389 llvm_unreachable("getGridValue not implemented for this wavesize");
393 /// \returns Target specific vtbl ptr address space.
394 unsigned getVtblPtrAddressSpace() const override {
395 return static_cast<unsigned>(Constant);
398 /// \returns If a target requires an address within a target specific address
399 /// space \p AddressSpace to be converted in order to be used, then return the
400 /// corresponding target specific DWARF address space.
402 /// \returns Otherwise return std::nullopt and no conversion will be emitted
403 /// in the DWARF.
404 std::optional<unsigned>
405 getDWARFAddressSpace(unsigned AddressSpace) const override {
406 const unsigned DWARF_Private = 1;
407 const unsigned DWARF_Local = 2;
408 if (AddressSpace == Private) {
409 return DWARF_Private;
410 } else if (AddressSpace == Local) {
411 return DWARF_Local;
412 } else {
413 return std::nullopt;
417 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
418 switch (CC) {
419 default:
420 return CCCR_Warning;
421 case CC_C:
422 case CC_OpenCLKernel:
423 case CC_AMDGPUKernelCall:
424 return CCCR_OK;
428 // In amdgcn target the null pointer in global, constant, and generic
429 // address space has value 0 but in private and local address space has
430 // value ~0.
431 uint64_t getNullPointerValue(LangAS AS) const override {
432 // FIXME: Also should handle region.
433 return (AS == LangAS::opencl_local || AS == LangAS::opencl_private)
434 ? ~0 : 0;
437 void setAuxTarget(const TargetInfo *Aux) override;
439 bool hasBitIntType() const override { return true; }
441 // Record offload arch features since they are needed for defining the
442 // pre-defined macros.
443 bool handleTargetFeatures(std::vector<std::string> &Features,
444 DiagnosticsEngine &Diags) override {
445 auto TargetIDFeatures =
446 getAllPossibleTargetIDFeatures(getTriple(), getArchNameAMDGCN(GPUKind));
447 for (const auto &F : Features) {
448 assert(F.front() == '+' || F.front() == '-');
449 if (F == "+wavefrontsize64")
450 WavefrontSize = 64;
451 else if (F == "+cumode")
452 CUMode = true;
453 else if (F == "-cumode")
454 CUMode = false;
455 else if (F == "+image-insts")
456 HasImage = true;
457 bool IsOn = F.front() == '+';
458 StringRef Name = StringRef(F).drop_front();
459 if (!llvm::is_contained(TargetIDFeatures, Name))
460 continue;
461 assert(!OffloadArchFeatures.contains(Name));
462 OffloadArchFeatures[Name] = IsOn;
464 return true;
467 std::optional<std::string> getTargetID() const override {
468 if (!isAMDGCN(getTriple()))
469 return std::nullopt;
470 // When -target-cpu is not set, we assume generic code that it is valid
471 // for all GPU and use an empty string as target ID to represent that.
472 if (GPUKind == llvm::AMDGPU::GK_NONE)
473 return std::string("");
474 return getCanonicalTargetID(getArchNameAMDGCN(GPUKind),
475 OffloadArchFeatures);
478 bool hasHIPImageSupport() const override { return HasImage; }
481 } // namespace targets
482 } // namespace clang
484 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H