blob: e78e7666720deeafd88e80fc1d051e9dedbc5c01 [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Erich Keaneebba5922017-07-21 22:37:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file declares AMDGPU TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
14#define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
15
16#include "clang/Basic/TargetInfo.h"
17#include "clang/Basic/TargetOptions.h"
Yaxun Liu304f3492017-09-28 19:07:59 +000018#include "llvm/ADT/StringSet.h"
Erich Keaneebba5922017-07-21 22:37:03 +000019#include "llvm/ADT/Triple.h"
20#include "llvm/Support/Compiler.h"
Matt Arsenaultb666e732018-08-21 16:13:29 +000021#include "llvm/Support/TargetParser.h"
Erich Keaneebba5922017-07-21 22:37:03 +000022
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
Yaxun Liu1578a0a2018-03-05 17:50:10 +000031 enum AddrSpace {
32 Generic = 0,
33 Global = 1,
34 Local = 3,
35 Constant = 4,
36 Private = 5
Erich Keaneebba5922017-07-21 22:37:03 +000037 };
Yaxun Liu1578a0a2018-03-05 17:50:10 +000038 static const LangASMap AMDGPUDefIsGenMap;
39 static const LangASMap AMDGPUDefIsPrivMap;
Erich Keaneebba5922017-07-21 22:37:03 +000040
Matt Arsenaultb666e732018-08-21 16:13:29 +000041 llvm::AMDGPU::GPUKind GPUKind;
42 unsigned GPUFeatures;
Konstantin Zhuravlyovd6b34532018-02-27 21:48:05 +000043
Konstantin Zhuravlyovd6b34532018-02-27 21:48:05 +000044
Matt Arsenaultb666e732018-08-21 16:13:29 +000045 bool hasFP64() const {
46 return getTriple().getArch() == llvm::Triple::amdgcn ||
47 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64);
48 }
Konstantin Zhuravlyovd6b34532018-02-27 21:48:05 +000049
Matt Arsenaultb666e732018-08-21 16:13:29 +000050 /// Has fast fma f32
51 bool hasFastFMAF() const {
52 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
53 }
Konstantin Zhuravlyovd6b34532018-02-27 21:48:05 +000054
Matt Arsenaultb666e732018-08-21 16:13:29 +000055 /// Has fast fma f64
56 bool hasFastFMA() const {
57 return getTriple().getArch() == llvm::Triple::amdgcn;
58 }
Erich Keaneebba5922017-07-21 22:37:03 +000059
Matt Arsenaultb666e732018-08-21 16:13:29 +000060 bool hasFMAF() const {
61 return getTriple().getArch() == llvm::Triple::amdgcn ||
62 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA);
63 }
Erich Keanee44bdb32018-02-08 23:16:55 +000064
Matt Arsenaultb666e732018-08-21 16:13:29 +000065 bool hasFullRateDenormalsF32() const {
66 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
67 }
Erich Keanee44bdb32018-02-08 23:16:55 +000068
Matt Arsenaultb666e732018-08-21 16:13:29 +000069 bool hasLDEXPF() const {
70 return getTriple().getArch() == llvm::Triple::amdgcn ||
71 !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP);
72 }
Erich Keaneebba5922017-07-21 22:37:03 +000073
74 static bool isAMDGCN(const llvm::Triple &TT) {
75 return TT.getArch() == llvm::Triple::amdgcn;
76 }
77
Matt Arsenaultb666e732018-08-21 16:13:29 +000078 static bool isR600(const llvm::Triple &TT) {
79 return TT.getArch() == llvm::Triple::r600;
80 }
81
Erich Keaneebba5922017-07-21 22:37:03 +000082public:
83 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
84
85 void setAddressSpaceMap(bool DefaultIsPrivate);
86
87 void adjust(LangOptions &Opts) override;
88
89 uint64_t getPointerWidthV(unsigned AddrSpace) const override {
Matt Arsenaultb666e732018-08-21 16:13:29 +000090 if (isR600(getTriple()))
Erich Keaneebba5922017-07-21 22:37:03 +000091 return 32;
Matt Arsenaultb666e732018-08-21 16:13:29 +000092
Yaxun Liu1578a0a2018-03-05 17:50:10 +000093 if (AddrSpace == Private || AddrSpace == Local)
Erich Keaneebba5922017-07-21 22:37:03 +000094 return 32;
Matt Arsenaultb666e732018-08-21 16:13:29 +000095
Erich Keaneebba5922017-07-21 22:37:03 +000096 return 64;
97 }
98
99 uint64_t getPointerAlignV(unsigned AddrSpace) const override {
100 return getPointerWidthV(AddrSpace);
101 }
102
103 uint64_t getMaxPointerWidth() const override {
104 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
105 }
106
107 const char *getClobbers() const override { return ""; }
108
109 ArrayRef<const char *> getGCCRegNames() const override;
110
111 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
112 return None;
113 }
114
Yaxun Liu304f3492017-09-28 19:07:59 +0000115 /// Accepted register names: (n, m is unsigned integer, n < m)
116 /// v
117 /// s
118 /// {vn}, {v[n]}
119 /// {sn}, {s[n]}
120 /// {S} , where S is a special register name
121 ////{v[n:m]}
122 /// {s[n:m]}
Erich Keaneebba5922017-07-21 22:37:03 +0000123 bool validateAsmConstraint(const char *&Name,
124 TargetInfo::ConstraintInfo &Info) const override {
Yaxun Liu304f3492017-09-28 19:07:59 +0000125 static const ::llvm::StringSet<> SpecialRegs({
126 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
127 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
128 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
129 });
130
131 StringRef S(Name);
132 bool HasLeftParen = false;
133 if (S.front() == '{') {
134 HasLeftParen = true;
135 S = S.drop_front();
136 }
137 if (S.empty())
138 return false;
139 if (S.front() != 'v' && S.front() != 's') {
140 if (!HasLeftParen)
141 return false;
142 auto E = S.find('}');
143 if (!SpecialRegs.count(S.substr(0, E)))
144 return false;
145 S = S.drop_front(E + 1);
146 if (!S.empty())
147 return false;
148 // Found {S} where S is a special register.
Erich Keaneebba5922017-07-21 22:37:03 +0000149 Info.setAllowsRegister();
Yaxun Liu304f3492017-09-28 19:07:59 +0000150 Name = S.data() - 1;
Erich Keaneebba5922017-07-21 22:37:03 +0000151 return true;
152 }
Yaxun Liu304f3492017-09-28 19:07:59 +0000153 S = S.drop_front();
154 if (!HasLeftParen) {
155 if (!S.empty())
156 return false;
157 // Found s or v.
158 Info.setAllowsRegister();
159 Name = S.data() - 1;
160 return true;
161 }
162 bool HasLeftBracket = false;
163 if (!S.empty() && S.front() == '[') {
164 HasLeftBracket = true;
165 S = S.drop_front();
166 }
167 unsigned long long N;
168 if (S.empty() || consumeUnsignedInteger(S, 10, N))
169 return false;
170 if (!S.empty() && S.front() == ':') {
171 if (!HasLeftBracket)
172 return false;
173 S = S.drop_front();
174 unsigned long long M;
175 if (consumeUnsignedInteger(S, 10, M) || N >= M)
176 return false;
177 }
178 if (HasLeftBracket) {
179 if (S.empty() || S.front() != ']')
180 return false;
181 S = S.drop_front();
182 }
183 if (S.empty() || S.front() != '}')
184 return false;
185 S = S.drop_front();
186 if (!S.empty())
187 return false;
188 // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
189 Info.setAllowsRegister();
190 Name = S.data() - 1;
191 return true;
Erich Keaneebba5922017-07-21 22:37:03 +0000192 }
193
Yaxun Liuac1263c2018-03-23 19:43:42 +0000194 // \p Constraint will be left pointing at the last character of
195 // the constraint. In practice, it won't be changed unless the
196 // constraint is longer than one character.
197 std::string convertConstraint(const char *&Constraint) const override {
198 const char *Begin = Constraint;
199 TargetInfo::ConstraintInfo Info("", "");
200 if (validateAsmConstraint(Constraint, Info))
201 return std::string(Begin).substr(0, Constraint - Begin + 1);
202
203 Constraint = Begin;
204 return std::string(1, *Constraint);
205 }
206
Erich Keaneebba5922017-07-21 22:37:03 +0000207 bool
208 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
209 StringRef CPU,
210 const std::vector<std::string> &FeatureVec) const override;
211
212 void adjustTargetOptions(const CodeGenOptions &CGOpts,
213 TargetOptions &TargetOpts) const override;
214
215 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
216
217 void getTargetDefines(const LangOptions &Opts,
218 MacroBuilder &Builder) const override;
219
220 BuiltinVaListKind getBuiltinVaListKind() const override {
221 return TargetInfo::CharPtrBuiltinVaList;
222 }
223
Erich Keaneebba5922017-07-21 22:37:03 +0000224 bool isValidCPUName(StringRef Name) const override {
225 if (getTriple().getArch() == llvm::Triple::amdgcn)
Matt Arsenaultb666e732018-08-21 16:13:29 +0000226 return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
227 return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
Erich Keaneebba5922017-07-21 22:37:03 +0000228 }
229
Erich Keanee44bdb32018-02-08 23:16:55 +0000230 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
231
Erich Keaneebba5922017-07-21 22:37:03 +0000232 bool setCPU(const std::string &Name) override {
Matt Arsenaultb666e732018-08-21 16:13:29 +0000233 if (getTriple().getArch() == llvm::Triple::amdgcn) {
234 GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
235 GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
236 } else {
237 GPUKind = llvm::AMDGPU::parseArchR600(Name);
238 GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
239 }
Erich Keaneebba5922017-07-21 22:37:03 +0000240
Matt Arsenaultb666e732018-08-21 16:13:29 +0000241 return GPUKind != llvm::AMDGPU::GK_NONE;
Erich Keaneebba5922017-07-21 22:37:03 +0000242 }
243
244 void setSupportedOpenCLOpts() override {
245 auto &Opts = getSupportedOpenCLOpts();
246 Opts.support("cl_clang_storage_class_specifiers");
247 Opts.support("cl_khr_icd");
248
Matt Arsenaultb666e732018-08-21 16:13:29 +0000249 bool IsAMDGCN = isAMDGCN(getTriple());
250
251 if (hasFP64())
Erich Keaneebba5922017-07-21 22:37:03 +0000252 Opts.support("cl_khr_fp64");
Matt Arsenaultb666e732018-08-21 16:13:29 +0000253
254 if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
Erich Keaneebba5922017-07-21 22:37:03 +0000255 Opts.support("cl_khr_byte_addressable_store");
256 Opts.support("cl_khr_global_int32_base_atomics");
257 Opts.support("cl_khr_global_int32_extended_atomics");
258 Opts.support("cl_khr_local_int32_base_atomics");
259 Opts.support("cl_khr_local_int32_extended_atomics");
260 }
Matt Arsenaultb666e732018-08-21 16:13:29 +0000261
262 if (IsAMDGCN) {
Erich Keaneebba5922017-07-21 22:37:03 +0000263 Opts.support("cl_khr_fp16");
264 Opts.support("cl_khr_int64_base_atomics");
265 Opts.support("cl_khr_int64_extended_atomics");
266 Opts.support("cl_khr_mipmap_image");
267 Opts.support("cl_khr_subgroups");
268 Opts.support("cl_khr_3d_image_writes");
269 Opts.support("cl_amd_media_ops");
270 Opts.support("cl_amd_media_ops2");
271 }
272 }
273
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000274 LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
275 switch (TK) {
276 case OCLTK_Image:
277 return LangAS::opencl_constant;
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000278
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000279 case OCLTK_ClkEvent:
280 case OCLTK_Queue:
281 case OCLTK_ReserveID:
Yaxun Liue3779352017-09-13 18:50:42 +0000282 return LangAS::opencl_global;
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000283
284 default:
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +0000285 return TargetInfo::getOpenCLTypeAddrSpace(TK);
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +0000286 }
Erich Keaneebba5922017-07-21 22:37:03 +0000287 }
288
Matt Arsenaultc65f9662018-08-02 12:14:28 +0000289 LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
290 switch (AS) {
291 case 0:
292 return LangAS::opencl_generic;
293 case 1:
294 return LangAS::opencl_global;
295 case 3:
296 return LangAS::opencl_local;
297 case 4:
298 return LangAS::opencl_constant;
299 case 5:
300 return LangAS::opencl_private;
301 default:
302 return getLangASFromTargetAS(AS);
303 }
304 }
305
306 LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
307 return LangAS::Default;
308 }
309
Alexander Richardson6d989432017-10-15 18:48:14 +0000310 llvm::Optional<LangAS> getConstantAddressSpace() const override {
Yaxun Liu1578a0a2018-03-05 17:50:10 +0000311 return getLangASFromTargetAS(Constant);
Erich Keaneebba5922017-07-21 22:37:03 +0000312 }
313
314 /// \returns Target specific vtbl ptr address space.
Yaxun Liu1578a0a2018-03-05 17:50:10 +0000315 unsigned getVtblPtrAddressSpace() const override {
316 return static_cast<unsigned>(Constant);
317 }
Erich Keaneebba5922017-07-21 22:37:03 +0000318
319 /// \returns If a target requires an address within a target specific address
320 /// space \p AddressSpace to be converted in order to be used, then return the
321 /// corresponding target specific DWARF address space.
322 ///
323 /// \returns Otherwise return None and no conversion will be emitted in the
324 /// DWARF.
325 Optional<unsigned>
326 getDWARFAddressSpace(unsigned AddressSpace) const override {
327 const unsigned DWARF_Private = 1;
328 const unsigned DWARF_Local = 2;
Yaxun Liu1578a0a2018-03-05 17:50:10 +0000329 if (AddressSpace == Private) {
Erich Keaneebba5922017-07-21 22:37:03 +0000330 return DWARF_Private;
Yaxun Liu1578a0a2018-03-05 17:50:10 +0000331 } else if (AddressSpace == Local) {
Erich Keaneebba5922017-07-21 22:37:03 +0000332 return DWARF_Local;
333 } else {
334 return None;
335 }
336 }
337
338 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
339 switch (CC) {
340 default:
341 return CCCR_Warning;
342 case CC_C:
343 case CC_OpenCLKernel:
344 return CCCR_OK;
345 }
346 }
347
348 // In amdgcn target the null pointer in global, constant, and generic
349 // address space has value 0 but in private and local address space has
350 // value ~0.
Alexander Richardson6d989432017-10-15 18:48:14 +0000351 uint64_t getNullPointerValue(LangAS AS) const override {
Erich Keaneebba5922017-07-21 22:37:03 +0000352 return AS == LangAS::opencl_local ? ~0 : 0;
353 }
Yaxun Liu95f2ca52019-01-30 12:26:54 +0000354
355 void setAuxTarget(const TargetInfo *Aux) override;
Erich Keaneebba5922017-07-21 22:37:03 +0000356};
357
358} // namespace targets
359} // namespace clang
360
361#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H