Clang Project

clang_source_code/lib/Basic/Targets/AMDGPU.h
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.
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
23namespace clang {
24namespace targets {
25
26class 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  /// Has fast fma f32
51  bool hasFastFMAF() const {
52    return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
53  }
54
55  /// Has fast fma f64
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
82public:
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  /// Accepted register names: (n, m is unsigned integer, n < m)
116  /// v
117  /// s
118  /// {vn}, {v[n]}
119  /// {sn}, {s[n]}
120  /// {S} , where S is a special register name
121  ////{v[n:m]}
122  /// {s[n:m]}
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      // Found {S} where S is a special register.
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      // Found s or v.
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    // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
189    Info.setAllowsRegister();
190    Name = S.data() - 1;
191    return true;
192  }
193
194  // \p Constraint will be left pointing at the last character of
195  // the constraint.  In practice, it won't be changed unless the
196  // constraint is longer than one character.
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  /// \returns Target specific vtbl ptr address space.
315  unsigned getVtblPtrAddressSpace() const override {
316    return static_cast<unsigned>(Constant);
317  }
318
319  /// \returns If a target requires an address within a target specific address
320  /// space \p AddressSpace to be converted in order to be used, then return the
321  /// corresponding target specific DWARF address space.
322  ///
323  /// \returns Otherwise return None and no conversion will be emitted in the
324  /// DWARF.
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  // In amdgcn target the null pointer in global, constant, and generic
349  // address space has value 0 but in private and local address space has
350  // value ~0.
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// namespace targets
359// namespace clang
360
361#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
362