blob: a4e070f1cb12e6148dcc62a014b567f8dc500915 [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- 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"
Yaxun Liu304f3492017-09-28 19:07:59 +000019#include "llvm/ADT/StringSet.h"
Erich Keaneebba5922017-07-21 22:37:03 +000020#include "llvm/ADT/Triple.h"
21#include "llvm/Support/Compiler.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 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 } GPU;
66
67 bool hasFP64 : 1;
68 bool hasFMAF : 1;
69 bool hasLDEXPF : 1;
70 const AddrSpace AS;
71
72 static bool hasFullSpeedFMAF32(StringRef GPUName) {
73 return parseAMDGCNName(GPUName) >= GK_GFX9;
74 }
75
76 static bool isAMDGCN(const llvm::Triple &TT) {
77 return TT.getArch() == llvm::Triple::amdgcn;
78 }
79
80 static bool isGenericZero(const llvm::Triple &TT) {
81 return TT.getEnvironmentName() == "amdgiz" ||
82 TT.getEnvironmentName() == "amdgizcl";
83 }
84
85public:
86 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
87
88 void setAddressSpaceMap(bool DefaultIsPrivate);
89
90 void adjust(LangOptions &Opts) override;
91
92 uint64_t getPointerWidthV(unsigned AddrSpace) const override {
93 if (GPU <= GK_CAYMAN)
94 return 32;
95
96 if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
97 return 32;
98 }
99 return 64;
100 }
101
102 uint64_t getPointerAlignV(unsigned AddrSpace) const override {
103 return getPointerWidthV(AddrSpace);
104 }
105
106 uint64_t getMaxPointerWidth() const override {
107 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
108 }
109
110 const char *getClobbers() const override { return ""; }
111
112 ArrayRef<const char *> getGCCRegNames() const override;
113
114 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
115 return None;
116 }
117
Yaxun Liu304f3492017-09-28 19:07:59 +0000118 /// Accepted register names: (n, m is unsigned integer, n < m)
119 /// v
120 /// s
121 /// {vn}, {v[n]}
122 /// {sn}, {s[n]}
123 /// {S} , where S is a special register name
124 ////{v[n:m]}
125 /// {s[n:m]}
Erich Keaneebba5922017-07-21 22:37:03 +0000126 bool validateAsmConstraint(const char *&Name,
127 TargetInfo::ConstraintInfo &Info) const override {
Yaxun Liu304f3492017-09-28 19:07:59 +0000128 static const ::llvm::StringSet<> SpecialRegs({
129 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
130 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
131 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
132 });
133
134 StringRef S(Name);
135 bool HasLeftParen = false;
136 if (S.front() == '{') {
137 HasLeftParen = true;
138 S = S.drop_front();
139 }
140 if (S.empty())
141 return false;
142 if (S.front() != 'v' && S.front() != 's') {
143 if (!HasLeftParen)
144 return false;
145 auto E = S.find('}');
146 if (!SpecialRegs.count(S.substr(0, E)))
147 return false;
148 S = S.drop_front(E + 1);
149 if (!S.empty())
150 return false;
151 // Found {S} where S is a special register.
Erich Keaneebba5922017-07-21 22:37:03 +0000152 Info.setAllowsRegister();
Yaxun Liu304f3492017-09-28 19:07:59 +0000153 Name = S.data() - 1;
Erich Keaneebba5922017-07-21 22:37:03 +0000154 return true;
155 }
Yaxun Liu304f3492017-09-28 19:07:59 +0000156 S = S.drop_front();
157 if (!HasLeftParen) {
158 if (!S.empty())
159 return false;
160 // Found s or v.
161 Info.setAllowsRegister();
162 Name = S.data() - 1;
163 return true;
164 }
165 bool HasLeftBracket = false;
166 if (!S.empty() && S.front() == '[') {
167 HasLeftBracket = true;
168 S = S.drop_front();
169 }
170 unsigned long long N;
171 if (S.empty() || consumeUnsignedInteger(S, 10, N))
172 return false;
173 if (!S.empty() && S.front() == ':') {
174 if (!HasLeftBracket)
175 return false;
176 S = S.drop_front();
177 unsigned long long M;
178 if (consumeUnsignedInteger(S, 10, M) || N >= M)
179 return false;
180 }
181 if (HasLeftBracket) {
182 if (S.empty() || S.front() != ']')
183 return false;
184 S = S.drop_front();
185 }
186 if (S.empty() || S.front() != '}')
187 return false;
188 S = S.drop_front();
189 if (!S.empty())
190 return false;
191 // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
192 Info.setAllowsRegister();
193 Name = S.data() - 1;
194 return true;
Erich Keaneebba5922017-07-21 22:37:03 +0000195 }
196
197 bool
198 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
199 StringRef CPU,
200 const std::vector<std::string> &FeatureVec) const override;
201
202 void adjustTargetOptions(const CodeGenOptions &CGOpts,
203 TargetOptions &TargetOpts) const override;
204
205 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
206
207 void getTargetDefines(const LangOptions &Opts,
208 MacroBuilder &Builder) const override;
209
210 BuiltinVaListKind getBuiltinVaListKind() const override {
211 return TargetInfo::CharPtrBuiltinVaList;
212 }
213
214 static GPUKind parseR600Name(StringRef Name);
215
216 static GPUKind parseAMDGCNName(StringRef Name);
217
218 bool isValidCPUName(StringRef Name) const override {
219 if (getTriple().getArch() == llvm::Triple::amdgcn)
220 return GK_NONE != parseAMDGCNName(Name);
221 else
222 return GK_NONE != parseR600Name(Name);
223 }
224
225 bool setCPU(const std::string &Name) override {
226 if (getTriple().getArch() == llvm::Triple::amdgcn)
227 GPU = parseAMDGCNName(Name);
228 else
229 GPU = parseR600Name(Name);
230
231 return GPU != GK_NONE;
232 }
233
234 void setSupportedOpenCLOpts() override {
235 auto &Opts = getSupportedOpenCLOpts();
236 Opts.support("cl_clang_storage_class_specifiers");
237 Opts.support("cl_khr_icd");
238
239 if (hasFP64)
240 Opts.support("cl_khr_fp64");
241 if (GPU >= GK_EVERGREEN) {
242 Opts.support("cl_khr_byte_addressable_store");
243 Opts.support("cl_khr_global_int32_base_atomics");
244 Opts.support("cl_khr_global_int32_extended_atomics");
245 Opts.support("cl_khr_local_int32_base_atomics");
246 Opts.support("cl_khr_local_int32_extended_atomics");
247 }
248 if (GPU >= GK_GFX6) {
249 Opts.support("cl_khr_fp16");
250 Opts.support("cl_khr_int64_base_atomics");
251 Opts.support("cl_khr_int64_extended_atomics");
252 Opts.support("cl_khr_mipmap_image");
253 Opts.support("cl_khr_subgroups");
254 Opts.support("cl_khr_3d_image_writes");
255 Opts.support("cl_amd_media_ops");
256 Opts.support("cl_amd_media_ops2");
257 }
258 }
259
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000260 LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
261 switch (TK) {
262 case OCLTK_Image:
263 return LangAS::opencl_constant;
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000264
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000265 case OCLTK_ClkEvent:
266 case OCLTK_Queue:
267 case OCLTK_ReserveID:
Yaxun Liue3779352017-09-13 18:50:42 +0000268 return LangAS::opencl_global;
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000269
270 default:
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000271 return TargetInfo::getOpenCLTypeAddrSpace(TK);
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000272 }
Erich Keaneebba5922017-07-21 22:37:03 +0000273 }
274
Alexander Richardson6d989432017-10-15 18:48:14 +0000275 llvm::Optional<LangAS> getConstantAddressSpace() const override {
276 return getLangASFromTargetAS(AS.Constant);
Erich Keaneebba5922017-07-21 22:37:03 +0000277 }
278
279 /// \returns Target specific vtbl ptr address space.
280 unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
281
282 /// \returns If a target requires an address within a target specific address
283 /// space \p AddressSpace to be converted in order to be used, then return the
284 /// corresponding target specific DWARF address space.
285 ///
286 /// \returns Otherwise return None and no conversion will be emitted in the
287 /// DWARF.
288 Optional<unsigned>
289 getDWARFAddressSpace(unsigned AddressSpace) const override {
290 const unsigned DWARF_Private = 1;
291 const unsigned DWARF_Local = 2;
292 if (AddressSpace == AS.Private) {
293 return DWARF_Private;
294 } else if (AddressSpace == AS.Local) {
295 return DWARF_Local;
296 } else {
297 return None;
298 }
299 }
300
301 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
302 switch (CC) {
303 default:
304 return CCCR_Warning;
305 case CC_C:
306 case CC_OpenCLKernel:
307 return CCCR_OK;
308 }
309 }
310
311 // In amdgcn target the null pointer in global, constant, and generic
312 // address space has value 0 but in private and local address space has
313 // value ~0.
Alexander Richardson6d989432017-10-15 18:48:14 +0000314 uint64_t getNullPointerValue(LangAS AS) const override {
Erich Keaneebba5922017-07-21 22:37:03 +0000315 return AS == LangAS::opencl_local ? ~0 : 0;
316 }
317};
318
319} // namespace targets
320} // namespace clang
321
322#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H