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