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