1 //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares AMDGPU TargetInfo objects.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
15 #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
16 
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/TargetOptions.h"
19 #include "llvm/ADT/StringSet.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Support/Compiler.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   /// GPU kinds supported by the AMDGPU target.
42   enum GPUKind : uint32_t {
43     // Not specified processor.
44     GK_NONE = 0,
45 
46     // R600-based processors.
47     GK_R600,
48     GK_R630,
49     GK_RS880,
50     GK_RV670,
51     GK_RV710,
52     GK_RV730,
53     GK_RV770,
54     GK_CEDAR,
55     GK_CYPRESS,
56     GK_JUNIPER,
57     GK_REDWOOD,
58     GK_SUMO,
59     GK_BARTS,
60     GK_CAICOS,
61     GK_CAYMAN,
62     GK_TURKS,
63 
64     GK_R600_FIRST = GK_R600,
65     GK_R600_LAST = GK_TURKS,
66 
67     // AMDGCN-based processors.
68     GK_GFX600,
69     GK_GFX601,
70     GK_GFX700,
71     GK_GFX701,
72     GK_GFX702,
73     GK_GFX703,
74     GK_GFX704,
75     GK_GFX801,
76     GK_GFX802,
77     GK_GFX803,
78     GK_GFX810,
79     GK_GFX900,
80     GK_GFX902,
81     GK_GFX904,
82     GK_GFX906,
83 
84     GK_AMDGCN_FIRST = GK_GFX600,
85     GK_AMDGCN_LAST = GK_GFX906,
86   };
87 
88   struct GPUInfo {
89     llvm::StringLiteral Name;
90     llvm::StringLiteral CanonicalName;
91     AMDGPUTargetInfo::GPUKind Kind;
92     bool HasFMAF;
93     bool HasFastFMAF;
94     bool HasLDEXPF;
95     bool HasFP64;
96     bool HasFastFMA;
97     bool HasFullRateF32Denorms;
98   };
99 
100   static constexpr GPUInfo InvalidGPU =
101     {{""}, {""}, GK_NONE, false, false, false, false, false, false};
102   static constexpr GPUInfo R600GPUs[26] = {
103   // Name         Canonical    Kind        Has    Has    Has    Has    Has    Has
104   //              Name                     FMAF   Fast   LDEXPF FP64   Fast   Fast
105   //                                              FMAF                 FMA    Denorm
106     {{"r600"},    {"r600"},    GK_R600,    false, false, false, false, false, false},
107     {{"rv630"},   {"r600"},    GK_R600,    false, false, false, false, false, false},
108     {{"rv635"},   {"r600"},    GK_R600,    false, false, false, false, false, false},
109     {{"r630"},    {"r630"},    GK_R630,    false, false, false, false, false, false},
110     {{"rs780"},   {"rs880"},   GK_RS880,   false, false, false, false, false, false},
111     {{"rs880"},   {"rs880"},   GK_RS880,   false, false, false, false, false, false},
112     {{"rv610"},   {"rs880"},   GK_RS880,   false, false, false, false, false, false},
113     {{"rv620"},   {"rs880"},   GK_RS880,   false, false, false, false, false, false},
114     {{"rv670"},   {"rv670"},   GK_RV670,   false, false, false, false, false, false},
115     {{"rv710"},   {"rv710"},   GK_RV710,   false, false, false, false, false, false},
116     {{"rv730"},   {"rv730"},   GK_RV730,   false, false, false, false, false, false},
117     {{"rv740"},   {"rv770"},   GK_RV770,   false, false, false, false, false, false},
118     {{"rv770"},   {"rv770"},   GK_RV770,   false, false, false, false, false, false},
119     {{"cedar"},   {"cedar"},   GK_CEDAR,   false, false, false, false, false, false},
120     {{"palm"},    {"cedar"},   GK_CEDAR,   false, false, false, false, false, false},
121     {{"cypress"}, {"cypress"}, GK_CYPRESS, true,  false, false, false, false, false},
122     {{"hemlock"}, {"cypress"}, GK_CYPRESS, true,  false, false, false, false, false},
123     {{"juniper"}, {"juniper"}, GK_JUNIPER, false, false, false, false, false, false},
124     {{"redwood"}, {"redwood"}, GK_REDWOOD, false, false, false, false, false, false},
125     {{"sumo"},    {"sumo"},    GK_SUMO,    false, false, false, false, false, false},
126     {{"sumo2"},   {"sumo"},    GK_SUMO,    false, false, false, false, false, false},
127     {{"barts"},   {"barts"},   GK_BARTS,   false, false, false, false, false, false},
128     {{"caicos"},  {"caicos"},  GK_BARTS,   false, false, false, false, false, false},
129     {{"aruba"},   {"cayman"},  GK_CAYMAN,  true,  false, false, false, false, false},
130     {{"cayman"},  {"cayman"},  GK_CAYMAN,  true,  false, false, false, false, false},
131     {{"turks"},   {"turks"},   GK_TURKS,   false, false, false, false, false, false},
132   };
133   static constexpr GPUInfo AMDGCNGPUs[32] = {
134   // Name           Canonical    Kind        Has   Has    Has    Has   Has   Has
135   //                Name                     FMAF  Fast   LDEXPF FP64  Fast  Fast
136   //                                               FMAF                FMA   Denorm
137     {{"gfx600"},    {"gfx600"},  GK_GFX600,  true, true,  true,  true, true, false},
138     {{"tahiti"},    {"gfx600"},  GK_GFX600,  true, true,  true,  true, true, false},
139     {{"gfx601"},    {"gfx601"},  GK_GFX601,  true, false, true,  true, true, false},
140     {{"hainan"},    {"gfx601"},  GK_GFX601,  true, false, true,  true, true, false},
141     {{"oland"},     {"gfx601"},  GK_GFX601,  true, false, true,  true, true, false},
142     {{"pitcairn"},  {"gfx601"},  GK_GFX601,  true, false, true,  true, true, false},
143     {{"verde"},     {"gfx601"},  GK_GFX601,  true, false, true,  true, true, false},
144     {{"gfx700"},    {"gfx700"},  GK_GFX700,  true, false, true,  true, true, false},
145     {{"kaveri"},    {"gfx700"},  GK_GFX700,  true, false, true,  true, true, false},
146     {{"gfx701"},    {"gfx701"},  GK_GFX701,  true, true,  true,  true, true, false},
147     {{"hawaii"},    {"gfx701"},  GK_GFX701,  true, true,  true,  true, true, false},
148     {{"gfx702"},    {"gfx702"},  GK_GFX702,  true, true,  true,  true, true, false},
149     {{"gfx703"},    {"gfx703"},  GK_GFX703,  true, false, true,  true, true, false},
150     {{"kabini"},    {"gfx703"},  GK_GFX703,  true, false, true,  true, true, false},
151     {{"mullins"},   {"gfx703"},  GK_GFX703,  true, false, true,  true, true, false},
152     {{"gfx704"},    {"gfx704"},  GK_GFX704,  true, false, true,  true, true, false},
153     {{"bonaire"},   {"gfx704"},  GK_GFX704,  true, false, true,  true, true, false},
154     {{"gfx801"},    {"gfx801"},  GK_GFX801,  true, true,  true,  true, true, true},
155     {{"carrizo"},   {"gfx801"},  GK_GFX801,  true, true,  true,  true, true, true},
156     {{"gfx802"},    {"gfx802"},  GK_GFX802,  true, false, true,  true, true, true},
157     {{"iceland"},   {"gfx802"},  GK_GFX802,  true, false, true,  true, true, true},
158     {{"tonga"},     {"gfx802"},  GK_GFX802,  true, false, true,  true, true, true},
159     {{"gfx803"},    {"gfx803"},  GK_GFX803,  true, false, true,  true, true, true},
160     {{"fiji"},      {"gfx803"},  GK_GFX803,  true, false, true,  true, true, true},
161     {{"polaris10"}, {"gfx803"},  GK_GFX803,  true, false, true,  true, true, true},
162     {{"polaris11"}, {"gfx803"},  GK_GFX803,  true, false, true,  true, true, true},
163     {{"gfx810"},    {"gfx810"},  GK_GFX810,  true, false, true,  true, true, true},
164     {{"stoney"},    {"gfx810"},  GK_GFX810,  true, false, true,  true, true, true},
165     {{"gfx900"},    {"gfx900"},  GK_GFX900,  true, true,  true,  true, true, true},
166     {{"gfx902"},    {"gfx902"},  GK_GFX900,  true, true,  true,  true, true, true},
167     {{"gfx904"},    {"gfx904"},  GK_GFX904,  true, true,  true,  true, true, true},
168     {{"gfx906"},    {"gfx906"},  GK_GFX906,  true, true,  true,  true, true, true},
169   };
170 
171   static GPUInfo parseR600Name(StringRef Name);
172 
173   static GPUInfo parseAMDGCNName(StringRef Name);
174 
175   GPUInfo parseGPUName(StringRef Name) const;
176 
177   GPUInfo GPU;
178 
179   static bool isAMDGCN(const llvm::Triple &TT) {
180     return TT.getArch() == llvm::Triple::amdgcn;
181   }
182 
183 public:
184   AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
185 
186   void setAddressSpaceMap(bool DefaultIsPrivate);
187 
188   void adjust(LangOptions &Opts) override;
189 
190   uint64_t getPointerWidthV(unsigned AddrSpace) const override {
191     if (GPU.Kind <= GK_R600_LAST)
192       return 32;
193     if (AddrSpace == Private || AddrSpace == Local)
194       return 32;
195     return 64;
196   }
197 
198   uint64_t getPointerAlignV(unsigned AddrSpace) const override {
199     return getPointerWidthV(AddrSpace);
200   }
201 
202   uint64_t getMaxPointerWidth() const override {
203     return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
204   }
205 
206   const char *getClobbers() const override { return ""; }
207 
208   ArrayRef<const char *> getGCCRegNames() const override;
209 
210   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
211     return None;
212   }
213 
214   /// Accepted register names: (n, m is unsigned integer, n < m)
215   /// v
216   /// s
217   /// {vn}, {v[n]}
218   /// {sn}, {s[n]}
219   /// {S} , where S is a special register name
220   ////{v[n:m]}
221   /// {s[n:m]}
222   bool validateAsmConstraint(const char *&Name,
223                              TargetInfo::ConstraintInfo &Info) const override {
224     static const ::llvm::StringSet<> SpecialRegs({
225         "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
226         "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
227         "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
228     });
229 
230     StringRef S(Name);
231     bool HasLeftParen = false;
232     if (S.front() == '{') {
233       HasLeftParen = true;
234       S = S.drop_front();
235     }
236     if (S.empty())
237       return false;
238     if (S.front() != 'v' && S.front() != 's') {
239       if (!HasLeftParen)
240         return false;
241       auto E = S.find('}');
242       if (!SpecialRegs.count(S.substr(0, E)))
243         return false;
244       S = S.drop_front(E + 1);
245       if (!S.empty())
246         return false;
247       // Found {S} where S is a special register.
248       Info.setAllowsRegister();
249       Name = S.data() - 1;
250       return true;
251     }
252     S = S.drop_front();
253     if (!HasLeftParen) {
254       if (!S.empty())
255         return false;
256       // Found s or v.
257       Info.setAllowsRegister();
258       Name = S.data() - 1;
259       return true;
260     }
261     bool HasLeftBracket = false;
262     if (!S.empty() && S.front() == '[') {
263       HasLeftBracket = true;
264       S = S.drop_front();
265     }
266     unsigned long long N;
267     if (S.empty() || consumeUnsignedInteger(S, 10, N))
268       return false;
269     if (!S.empty() && S.front() == ':') {
270       if (!HasLeftBracket)
271         return false;
272       S = S.drop_front();
273       unsigned long long M;
274       if (consumeUnsignedInteger(S, 10, M) || N >= M)
275         return false;
276     }
277     if (HasLeftBracket) {
278       if (S.empty() || S.front() != ']')
279         return false;
280       S = S.drop_front();
281     }
282     if (S.empty() || S.front() != '}')
283       return false;
284     S = S.drop_front();
285     if (!S.empty())
286       return false;
287     // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
288     Info.setAllowsRegister();
289     Name = S.data() - 1;
290     return true;
291   }
292 
293   // \p Constraint will be left pointing at the last character of
294   // the constraint.  In practice, it won't be changed unless the
295   // constraint is longer than one character.
296   std::string convertConstraint(const char *&Constraint) const override {
297     const char *Begin = Constraint;
298     TargetInfo::ConstraintInfo Info("", "");
299     if (validateAsmConstraint(Constraint, Info))
300       return std::string(Begin).substr(0, Constraint - Begin + 1);
301 
302     Constraint = Begin;
303     return std::string(1, *Constraint);
304   }
305 
306   bool
307   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
308                  StringRef CPU,
309                  const std::vector<std::string> &FeatureVec) const override;
310 
311   void adjustTargetOptions(const CodeGenOptions &CGOpts,
312                            TargetOptions &TargetOpts) const override;
313 
314   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
315 
316   void getTargetDefines(const LangOptions &Opts,
317                         MacroBuilder &Builder) const override;
318 
319   BuiltinVaListKind getBuiltinVaListKind() const override {
320     return TargetInfo::CharPtrBuiltinVaList;
321   }
322 
323   bool isValidCPUName(StringRef Name) const override {
324     if (getTriple().getArch() == llvm::Triple::amdgcn)
325       return GK_NONE != parseAMDGCNName(Name).Kind;
326     else
327       return GK_NONE != parseR600Name(Name).Kind;
328   }
329 
330   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
331 
332   bool setCPU(const std::string &Name) override {
333     if (getTriple().getArch() == llvm::Triple::amdgcn)
334       GPU = parseAMDGCNName(Name);
335     else
336       GPU = parseR600Name(Name);
337 
338     return GK_NONE != GPU.Kind;
339   }
340 
341   void setSupportedOpenCLOpts() override {
342     auto &Opts = getSupportedOpenCLOpts();
343     Opts.support("cl_clang_storage_class_specifiers");
344     Opts.support("cl_khr_icd");
345 
346     if (GPU.HasFP64)
347       Opts.support("cl_khr_fp64");
348     if (GPU.Kind >= GK_CEDAR) {
349       Opts.support("cl_khr_byte_addressable_store");
350       Opts.support("cl_khr_global_int32_base_atomics");
351       Opts.support("cl_khr_global_int32_extended_atomics");
352       Opts.support("cl_khr_local_int32_base_atomics");
353       Opts.support("cl_khr_local_int32_extended_atomics");
354     }
355     if (GPU.Kind >= GK_AMDGCN_FIRST) {
356       Opts.support("cl_khr_fp16");
357       Opts.support("cl_khr_int64_base_atomics");
358       Opts.support("cl_khr_int64_extended_atomics");
359       Opts.support("cl_khr_mipmap_image");
360       Opts.support("cl_khr_subgroups");
361       Opts.support("cl_khr_3d_image_writes");
362       Opts.support("cl_amd_media_ops");
363       Opts.support("cl_amd_media_ops2");
364     }
365   }
366 
367   LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
368     switch (TK) {
369     case OCLTK_Image:
370       return LangAS::opencl_constant;
371 
372     case OCLTK_ClkEvent:
373     case OCLTK_Queue:
374     case OCLTK_ReserveID:
375       return LangAS::opencl_global;
376 
377     default:
378       return TargetInfo::getOpenCLTypeAddrSpace(TK);
379     }
380   }
381 
382   LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
383     switch (AS) {
384     case 0:
385       return LangAS::opencl_generic;
386     case 1:
387       return LangAS::opencl_global;
388     case 3:
389       return LangAS::opencl_local;
390     case 4:
391       return LangAS::opencl_constant;
392     case 5:
393       return LangAS::opencl_private;
394     default:
395       return getLangASFromTargetAS(AS);
396     }
397   }
398 
399   LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
400     return LangAS::Default;
401   }
402 
403   llvm::Optional<LangAS> getConstantAddressSpace() const override {
404     return getLangASFromTargetAS(Constant);
405   }
406 
407   /// \returns Target specific vtbl ptr address space.
408   unsigned getVtblPtrAddressSpace() const override {
409     return static_cast<unsigned>(Constant);
410   }
411 
412   /// \returns If a target requires an address within a target specific address
413   /// space \p AddressSpace to be converted in order to be used, then return the
414   /// corresponding target specific DWARF address space.
415   ///
416   /// \returns Otherwise return None and no conversion will be emitted in the
417   /// DWARF.
418   Optional<unsigned>
419   getDWARFAddressSpace(unsigned AddressSpace) const override {
420     const unsigned DWARF_Private = 1;
421     const unsigned DWARF_Local = 2;
422     if (AddressSpace == Private) {
423       return DWARF_Private;
424     } else if (AddressSpace == Local) {
425       return DWARF_Local;
426     } else {
427       return None;
428     }
429   }
430 
431   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
432     switch (CC) {
433     default:
434       return CCCR_Warning;
435     case CC_C:
436     case CC_OpenCLKernel:
437       return CCCR_OK;
438     }
439   }
440 
441   // In amdgcn target the null pointer in global, constant, and generic
442   // address space has value 0 but in private and local address space has
443   // value ~0.
444   uint64_t getNullPointerValue(LangAS AS) const override {
445     return AS == LangAS::opencl_local ? ~0 : 0;
446   }
447 };
448 
449 } // namespace targets
450 } // namespace clang
451 
452 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
453