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