AMDGPU.h revision 1.1.1.2
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  /// a
118  /// {vn}, {v[n]}
119  /// {sn}, {s[n]}
120  /// {an}, {a[n]}
121  /// {S} , where S is a special register name
122  ////{v[n:m]}
123  /// {s[n:m]}
124  /// {a[n:m]}
125  bool validateAsmConstraint(const char *&Name,
126                             TargetInfo::ConstraintInfo &Info) const override {
127    static const ::llvm::StringSet<> SpecialRegs({
128        "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
129        "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
130        "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
131    });
132
133    switch (*Name) {
134    case 'I':
135      Info.setRequiresImmediate(-16, 64);
136      return true;
137    case 'J':
138      Info.setRequiresImmediate(-32768, 32767);
139      return true;
140    case 'A':
141    case 'B':
142    case 'C':
143      Info.setRequiresImmediate();
144      return true;
145    default:
146      break;
147    }
148
149    StringRef S(Name);
150
151    if (S == "DA" || S == "DB") {
152      Name++;
153      Info.setRequiresImmediate();
154      return true;
155    }
156
157    bool HasLeftParen = false;
158    if (S.front() == '{') {
159      HasLeftParen = true;
160      S = S.drop_front();
161    }
162    if (S.empty())
163      return false;
164    if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
165      if (!HasLeftParen)
166        return false;
167      auto E = S.find('}');
168      if (!SpecialRegs.count(S.substr(0, E)))
169        return false;
170      S = S.drop_front(E + 1);
171      if (!S.empty())
172        return false;
173      // Found {S} where S is a special register.
174      Info.setAllowsRegister();
175      Name = S.data() - 1;
176      return true;
177    }
178    S = S.drop_front();
179    if (!HasLeftParen) {
180      if (!S.empty())
181        return false;
182      // Found s, v or a.
183      Info.setAllowsRegister();
184      Name = S.data() - 1;
185      return true;
186    }
187    bool HasLeftBracket = false;
188    if (!S.empty() && S.front() == '[') {
189      HasLeftBracket = true;
190      S = S.drop_front();
191    }
192    unsigned long long N;
193    if (S.empty() || consumeUnsignedInteger(S, 10, N))
194      return false;
195    if (!S.empty() && S.front() == ':') {
196      if (!HasLeftBracket)
197        return false;
198      S = S.drop_front();
199      unsigned long long M;
200      if (consumeUnsignedInteger(S, 10, M) || N >= M)
201        return false;
202    }
203    if (HasLeftBracket) {
204      if (S.empty() || S.front() != ']')
205        return false;
206      S = S.drop_front();
207    }
208    if (S.empty() || S.front() != '}')
209      return false;
210    S = S.drop_front();
211    if (!S.empty())
212      return false;
213    // Found {vn}, {sn}, {an}, {v[n]}, {s[n]}, {a[n]}, {v[n:m]}, {s[n:m]}
214    // or {a[n:m]}.
215    Info.setAllowsRegister();
216    Name = S.data() - 1;
217    return true;
218  }
219
220  // \p Constraint will be left pointing at the last character of
221  // the constraint.  In practice, it won't be changed unless the
222  // constraint is longer than one character.
223  std::string convertConstraint(const char *&Constraint) const override {
224
225    StringRef S(Constraint);
226    if (S == "DA" || S == "DB") {
227      return std::string("^") + std::string(Constraint++, 2);
228    }
229
230    const char *Begin = Constraint;
231    TargetInfo::ConstraintInfo Info("", "");
232    if (validateAsmConstraint(Constraint, Info))
233      return std::string(Begin).substr(0, Constraint - Begin + 1);
234
235    Constraint = Begin;
236    return std::string(1, *Constraint);
237  }
238
239  bool
240  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
241                 StringRef CPU,
242                 const std::vector<std::string> &FeatureVec) const override;
243
244  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
245
246  bool useFP16ConversionIntrinsics() const override { return false; }
247
248  void getTargetDefines(const LangOptions &Opts,
249                        MacroBuilder &Builder) const override;
250
251  BuiltinVaListKind getBuiltinVaListKind() const override {
252    return TargetInfo::CharPtrBuiltinVaList;
253  }
254
255  bool isValidCPUName(StringRef Name) const override {
256    if (getTriple().getArch() == llvm::Triple::amdgcn)
257      return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
258    return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
259  }
260
261  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
262
263  bool setCPU(const std::string &Name) override {
264    if (getTriple().getArch() == llvm::Triple::amdgcn) {
265      GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
266      GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
267    } else {
268      GPUKind = llvm::AMDGPU::parseArchR600(Name);
269      GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
270    }
271
272    return GPUKind != llvm::AMDGPU::GK_NONE;
273  }
274
275  void setSupportedOpenCLOpts() override {
276    auto &Opts = getSupportedOpenCLOpts();
277    Opts.support("cl_clang_storage_class_specifiers");
278    Opts.support("cl_khr_icd");
279
280    bool IsAMDGCN = isAMDGCN(getTriple());
281
282    if (hasFP64())
283      Opts.support("cl_khr_fp64");
284
285    if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
286      Opts.support("cl_khr_byte_addressable_store");
287      Opts.support("cl_khr_global_int32_base_atomics");
288      Opts.support("cl_khr_global_int32_extended_atomics");
289      Opts.support("cl_khr_local_int32_base_atomics");
290      Opts.support("cl_khr_local_int32_extended_atomics");
291    }
292
293    if (IsAMDGCN) {
294      Opts.support("cl_khr_fp16");
295      Opts.support("cl_khr_int64_base_atomics");
296      Opts.support("cl_khr_int64_extended_atomics");
297      Opts.support("cl_khr_mipmap_image");
298      Opts.support("cl_khr_mipmap_image_writes");
299      Opts.support("cl_khr_subgroups");
300      Opts.support("cl_khr_3d_image_writes");
301      Opts.support("cl_amd_media_ops");
302      Opts.support("cl_amd_media_ops2");
303    }
304  }
305
306  LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
307    switch (TK) {
308    case OCLTK_Image:
309      return LangAS::opencl_constant;
310
311    case OCLTK_ClkEvent:
312    case OCLTK_Queue:
313    case OCLTK_ReserveID:
314      return LangAS::opencl_global;
315
316    default:
317      return TargetInfo::getOpenCLTypeAddrSpace(TK);
318    }
319  }
320
321  LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
322    switch (AS) {
323    case 0:
324      return LangAS::opencl_generic;
325    case 1:
326      return LangAS::opencl_global;
327    case 3:
328      return LangAS::opencl_local;
329    case 4:
330      return LangAS::opencl_constant;
331    case 5:
332      return LangAS::opencl_private;
333    default:
334      return getLangASFromTargetAS(AS);
335    }
336  }
337
338  LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
339    return LangAS::Default;
340  }
341
342  llvm::Optional<LangAS> getConstantAddressSpace() const override {
343    return getLangASFromTargetAS(Constant);
344  }
345
346  /// \returns Target specific vtbl ptr address space.
347  unsigned getVtblPtrAddressSpace() const override {
348    return static_cast<unsigned>(Constant);
349  }
350
351  /// \returns If a target requires an address within a target specific address
352  /// space \p AddressSpace to be converted in order to be used, then return the
353  /// corresponding target specific DWARF address space.
354  ///
355  /// \returns Otherwise return None and no conversion will be emitted in the
356  /// DWARF.
357  Optional<unsigned>
358  getDWARFAddressSpace(unsigned AddressSpace) const override {
359    const unsigned DWARF_Private = 1;
360    const unsigned DWARF_Local = 2;
361    if (AddressSpace == Private) {
362      return DWARF_Private;
363    } else if (AddressSpace == Local) {
364      return DWARF_Local;
365    } else {
366      return None;
367    }
368  }
369
370  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
371    switch (CC) {
372    default:
373      return CCCR_Warning;
374    case CC_C:
375    case CC_OpenCLKernel:
376      return CCCR_OK;
377    }
378  }
379
380  // In amdgcn target the null pointer in global, constant, and generic
381  // address space has value 0 but in private and local address space has
382  // value ~0.
383  uint64_t getNullPointerValue(LangAS AS) const override {
384    // FIXME: Also should handle region.
385    return (AS == LangAS::opencl_local || AS == LangAS::opencl_private)
386      ? ~0 : 0;
387  }
388
389  void setAuxTarget(const TargetInfo *Aux) override;
390
391  bool hasExtIntType() const override { return true; }
392};
393
394} // namespace targets
395} // namespace clang
396
397#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
398