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   struct LLVM_LIBRARY_VISIBILITY AddrSpace {
32     unsigned Generic, Global, Local, Constant, Private;
33     AddrSpace(bool IsGenericZero_ = false) {
34       if (IsGenericZero_) {
35         Generic = 0;
36         Global = 1;
37         Local = 3;
38         Constant = 2;
39         Private = 5;
40       } else {
41         Generic = 4;
42         Global = 1;
43         Local = 3;
44         Constant = 2;
45         Private = 0;
46       }
47     }
48   };
49 
50   /// \brief The GPU profiles supported by the AMDGPU target.
51   enum GPUKind {
52     GK_NONE,
53     GK_R600,
54     GK_R600_DOUBLE_OPS,
55     GK_R700,
56     GK_R700_DOUBLE_OPS,
57     GK_EVERGREEN,
58     GK_EVERGREEN_DOUBLE_OPS,
59     GK_NORTHERN_ISLANDS,
60     GK_CAYMAN,
61     GK_GFX6,
62     GK_GFX7,
63     GK_GFX8,
64     GK_GFX9
65   };
66 
67   struct GPUInfo {
68     llvm::StringLiteral Name;
69     llvm::StringLiteral CanonicalName;
70     AMDGPUTargetInfo::GPUKind Kind;
71   };
72 
73   GPUInfo GPU;
74 
75   static constexpr GPUInfo InvalidGPU = {{""}, {""}, GK_NONE};
76   static constexpr GPUInfo R600Names[26] = {
77       {{"r600"},    {"r600"},    GK_R600},
78       {{"rv630"},   {"r600"},    GK_R600},
79       {{"rv635"},   {"r600"},    GK_R600},
80       {{"r630"},    {"r630"},    GK_R600},
81       {{"rs780"},   {"rs880"},   GK_R600},
82       {{"rs880"},   {"rs880"},   GK_R600},
83       {{"rv610"},   {"rs880"},   GK_R600},
84       {{"rv620"},   {"rs880"},   GK_R600},
85       {{"rv670"},   {"rv670"},   GK_R600_DOUBLE_OPS},
86       {{"rv710"},   {"rv710"},   GK_R700},
87       {{"rv730"},   {"rv730"},   GK_R700},
88       {{"rv740"},   {"rv770"},   GK_R700_DOUBLE_OPS},
89       {{"rv770"},   {"rv770"},   GK_R700_DOUBLE_OPS},
90       {{"cedar"},   {"cedar"},   GK_EVERGREEN},
91       {{"palm"},    {"cedar"},   GK_EVERGREEN},
92       {{"cypress"}, {"cypress"}, GK_EVERGREEN_DOUBLE_OPS},
93       {{"hemlock"}, {"cypress"}, GK_EVERGREEN_DOUBLE_OPS},
94       {{"juniper"}, {"juniper"}, GK_EVERGREEN},
95       {{"redwood"}, {"redwood"}, GK_EVERGREEN},
96       {{"sumo"},    {"sumo"},    GK_EVERGREEN},
97       {{"sumo2"},   {"sumo"},    GK_EVERGREEN},
98       {{"barts"},   {"barts"},   GK_NORTHERN_ISLANDS},
99       {{"caicos"},  {"caicos"},  GK_NORTHERN_ISLANDS},
100       {{"turks"},   {"turks"},   GK_NORTHERN_ISLANDS},
101       {{"aruba"},   {"cayman"},  GK_CAYMAN},
102       {{"cayman"},  {"cayman"},  GK_CAYMAN},
103   };
104   static constexpr GPUInfo AMDGCNNames[30] = {
105       {{"gfx600"},    {"gfx600"}, GK_GFX6},
106       {{"tahiti"},    {"gfx600"}, GK_GFX6},
107       {{"gfx601"},    {"gfx601"}, GK_GFX6},
108       {{"hainan"},    {"gfx601"}, GK_GFX6},
109       {{"oland"},     {"gfx601"}, GK_GFX6},
110       {{"pitcairn"},  {"gfx601"}, GK_GFX6},
111       {{"verde"},     {"gfx601"}, GK_GFX6},
112       {{"gfx700"},    {"gfx700"}, GK_GFX7},
113       {{"kaveri"},    {"gfx700"}, GK_GFX7},
114       {{"gfx701"},    {"gfx701"}, GK_GFX7},
115       {{"hawaii"},    {"gfx701"}, GK_GFX7},
116       {{"gfx702"},    {"gfx702"}, GK_GFX7},
117       {{"gfx703"},    {"gfx703"}, GK_GFX7},
118       {{"kabini"},    {"gfx703"}, GK_GFX7},
119       {{"mullins"},   {"gfx703"}, GK_GFX7},
120       {{"gfx704"},    {"gfx704"}, GK_GFX7},
121       {{"bonaire"},   {"gfx704"}, GK_GFX7},
122       {{"gfx801"},    {"gfx801"}, GK_GFX8},
123       {{"carrizo"},   {"gfx801"}, GK_GFX8},
124       {{"gfx802"},    {"gfx802"}, GK_GFX8},
125       {{"iceland"},   {"gfx802"}, GK_GFX8},
126       {{"tonga"},     {"gfx802"}, GK_GFX8},
127       {{"gfx803"},    {"gfx803"}, GK_GFX8},
128       {{"fiji"},      {"gfx803"}, GK_GFX8},
129       {{"polaris10"}, {"gfx803"}, GK_GFX8},
130       {{"polaris11"}, {"gfx803"}, GK_GFX8},
131       {{"gfx810"},    {"gfx810"}, GK_GFX8},
132       {{"stoney"},    {"gfx810"}, GK_GFX8},
133       {{"gfx900"},    {"gfx900"}, GK_GFX9},
134       {{"gfx902"},    {"gfx902"}, GK_GFX9},
135   };
136 
137   bool hasFP64 : 1;
138   bool hasFMAF : 1;
139   bool hasLDEXPF : 1;
140   const AddrSpace AS;
141 
142   static bool hasFullSpeedFMAF32(StringRef GPUName) {
143     return parseAMDGCNName(GPUName).Kind >= GK_GFX9;
144   }
145 
146   static bool isAMDGCN(const llvm::Triple &TT) {
147     return TT.getArch() == llvm::Triple::amdgcn;
148   }
149 
150   static bool isGenericZero(const llvm::Triple &TT) { return true; }
151 
152 public:
153   AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
154 
155   void setAddressSpaceMap(bool DefaultIsPrivate);
156 
157   void adjust(LangOptions &Opts) override;
158 
159   uint64_t getPointerWidthV(unsigned AddrSpace) const override {
160     if (GPU.Kind <= GK_CAYMAN)
161       return 32;
162 
163     if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
164       return 32;
165     }
166     return 64;
167   }
168 
169   uint64_t getPointerAlignV(unsigned AddrSpace) const override {
170     return getPointerWidthV(AddrSpace);
171   }
172 
173   uint64_t getMaxPointerWidth() const override {
174     return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
175   }
176 
177   const char *getClobbers() const override { return ""; }
178 
179   ArrayRef<const char *> getGCCRegNames() const override;
180 
181   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
182     return None;
183   }
184 
185   /// Accepted register names: (n, m is unsigned integer, n < m)
186   /// v
187   /// s
188   /// {vn}, {v[n]}
189   /// {sn}, {s[n]}
190   /// {S} , where S is a special register name
191   ////{v[n:m]}
192   /// {s[n:m]}
193   bool validateAsmConstraint(const char *&Name,
194                              TargetInfo::ConstraintInfo &Info) const override {
195     static const ::llvm::StringSet<> SpecialRegs({
196         "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
197         "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
198         "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
199     });
200 
201     StringRef S(Name);
202     bool HasLeftParen = false;
203     if (S.front() == '{') {
204       HasLeftParen = true;
205       S = S.drop_front();
206     }
207     if (S.empty())
208       return false;
209     if (S.front() != 'v' && S.front() != 's') {
210       if (!HasLeftParen)
211         return false;
212       auto E = S.find('}');
213       if (!SpecialRegs.count(S.substr(0, E)))
214         return false;
215       S = S.drop_front(E + 1);
216       if (!S.empty())
217         return false;
218       // Found {S} where S is a special register.
219       Info.setAllowsRegister();
220       Name = S.data() - 1;
221       return true;
222     }
223     S = S.drop_front();
224     if (!HasLeftParen) {
225       if (!S.empty())
226         return false;
227       // Found s or v.
228       Info.setAllowsRegister();
229       Name = S.data() - 1;
230       return true;
231     }
232     bool HasLeftBracket = false;
233     if (!S.empty() && S.front() == '[') {
234       HasLeftBracket = true;
235       S = S.drop_front();
236     }
237     unsigned long long N;
238     if (S.empty() || consumeUnsignedInteger(S, 10, N))
239       return false;
240     if (!S.empty() && S.front() == ':') {
241       if (!HasLeftBracket)
242         return false;
243       S = S.drop_front();
244       unsigned long long M;
245       if (consumeUnsignedInteger(S, 10, M) || N >= M)
246         return false;
247     }
248     if (HasLeftBracket) {
249       if (S.empty() || S.front() != ']')
250         return false;
251       S = S.drop_front();
252     }
253     if (S.empty() || S.front() != '}')
254       return false;
255     S = S.drop_front();
256     if (!S.empty())
257       return false;
258     // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
259     Info.setAllowsRegister();
260     Name = S.data() - 1;
261     return true;
262   }
263 
264   bool
265   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
266                  StringRef CPU,
267                  const std::vector<std::string> &FeatureVec) const override;
268 
269   void adjustTargetOptions(const CodeGenOptions &CGOpts,
270                            TargetOptions &TargetOpts) const override;
271 
272   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
273 
274   void getTargetDefines(const LangOptions &Opts,
275                         MacroBuilder &Builder) const override;
276 
277   BuiltinVaListKind getBuiltinVaListKind() const override {
278     return TargetInfo::CharPtrBuiltinVaList;
279   }
280 
281   static GPUInfo parseR600Name(StringRef Name);
282 
283   static GPUInfo parseAMDGCNName(StringRef Name);
284 
285   bool isValidCPUName(StringRef Name) const override {
286     if (getTriple().getArch() == llvm::Triple::amdgcn)
287       return GK_NONE != parseAMDGCNName(Name).Kind;
288     else
289       return GK_NONE != parseR600Name(Name).Kind;
290   }
291 
292   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
293 
294   bool setCPU(const std::string &Name) override {
295     if (getTriple().getArch() == llvm::Triple::amdgcn)
296       GPU = parseAMDGCNName(Name);
297     else
298       GPU = parseR600Name(Name);
299 
300     return GPU.Kind != GK_NONE;
301   }
302 
303   void setSupportedOpenCLOpts() override {
304     auto &Opts = getSupportedOpenCLOpts();
305     Opts.support("cl_clang_storage_class_specifiers");
306     Opts.support("cl_khr_icd");
307 
308     if (hasFP64)
309       Opts.support("cl_khr_fp64");
310     if (GPU.Kind >= GK_EVERGREEN) {
311       Opts.support("cl_khr_byte_addressable_store");
312       Opts.support("cl_khr_global_int32_base_atomics");
313       Opts.support("cl_khr_global_int32_extended_atomics");
314       Opts.support("cl_khr_local_int32_base_atomics");
315       Opts.support("cl_khr_local_int32_extended_atomics");
316     }
317     if (GPU.Kind >= GK_GFX6) {
318       Opts.support("cl_khr_fp16");
319       Opts.support("cl_khr_int64_base_atomics");
320       Opts.support("cl_khr_int64_extended_atomics");
321       Opts.support("cl_khr_mipmap_image");
322       Opts.support("cl_khr_subgroups");
323       Opts.support("cl_khr_3d_image_writes");
324       Opts.support("cl_amd_media_ops");
325       Opts.support("cl_amd_media_ops2");
326     }
327   }
328 
329   LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
330     switch (TK) {
331     case OCLTK_Image:
332       return LangAS::opencl_constant;
333 
334     case OCLTK_ClkEvent:
335     case OCLTK_Queue:
336     case OCLTK_ReserveID:
337       return LangAS::opencl_global;
338 
339     default:
340       return TargetInfo::getOpenCLTypeAddrSpace(TK);
341     }
342   }
343 
344   llvm::Optional<LangAS> getConstantAddressSpace() const override {
345     return getLangASFromTargetAS(AS.Constant);
346   }
347 
348   /// \returns Target specific vtbl ptr address space.
349   unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
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 == AS.Private) {
362       return DWARF_Private;
363     } else if (AddressSpace == AS.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     return AS == LangAS::opencl_local ? ~0 : 0;
385   }
386 };
387 
388 } // namespace targets
389 } // namespace clang
390 
391 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
392