1 //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 // This file declares AMDGPU TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
14 #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Basic/TargetOptions.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/TargetParser.h"
26 class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
28 static const Builtin::Info BuiltinInfo[];
29 static const char *const GCCRegNames[];
38 static const LangASMap AMDGPUDefIsGenMap;
39 static const LangASMap AMDGPUDefIsPrivMap;
41 llvm::AMDGPU::GPUKind GPUKind;
44 bool hasFP64() const {
45 return getTriple().getArch() == llvm::Triple::amdgcn ||
46 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64);
50 bool hasFastFMAF() const {
51 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
55 bool hasFastFMA() const {
56 return getTriple().getArch() == llvm::Triple::amdgcn;
59 bool hasFMAF() const {
60 return getTriple().getArch() == llvm::Triple::amdgcn ||
61 !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA);
64 bool hasFullRateDenormalsF32() const {
65 return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
68 bool hasLDEXPF() const {
69 return getTriple().getArch() == llvm::Triple::amdgcn ||
70 !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP);
73 static bool isAMDGCN(const llvm::Triple &TT) {
74 return TT.getArch() == llvm::Triple::amdgcn;
77 static bool isR600(const llvm::Triple &TT) {
78 return TT.getArch() == llvm::Triple::r600;
82 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
84 void setAddressSpaceMap(bool DefaultIsPrivate);
86 void adjust(LangOptions &Opts) override;
88 uint64_t getPointerWidthV(unsigned AddrSpace) const override {
89 if (isR600(getTriple()))
92 if (AddrSpace == Private || AddrSpace == Local)
98 uint64_t getPointerAlignV(unsigned AddrSpace) const override {
99 return getPointerWidthV(AddrSpace);
102 uint64_t getMaxPointerWidth() const override {
103 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
106 const char *getClobbers() const override { return ""; }
108 ArrayRef<const char *> getGCCRegNames() const override;
110 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
114 /// Accepted register names: (n, m is unsigned integer, n < m)
121 /// {S} , where S is a special register name
125 bool validateAsmConstraint(const char *&Name,
126 TargetInfo::ConstraintInfo &Info) const override {
127 static const ::llvm::StringSet<> SpecialRegs({
128 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
129 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
130 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
135 Info.setRequiresImmediate(-16, 64);
138 Info.setRequiresImmediate(-32768, 32767);
143 Info.setRequiresImmediate();
151 if (S == "DA" || S == "DB") {
153 Info.setRequiresImmediate();
157 bool HasLeftParen = false;
158 if (S.front() == '{') {
164 if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
167 auto E = S.find('}');
168 if (!SpecialRegs.count(S.substr(0, E)))
170 S = S.drop_front(E + 1);
173 // Found {S} where S is a special register.
174 Info.setAllowsRegister();
183 Info.setAllowsRegister();
187 bool HasLeftBracket = false;
188 if (!S.empty() && S.front() == '[') {
189 HasLeftBracket = true;
192 unsigned long long N;
193 if (S.empty() || consumeUnsignedInteger(S, 10, N))
195 if (!S.empty() && S.front() == ':') {
199 unsigned long long M;
200 if (consumeUnsignedInteger(S, 10, M) || N >= M)
203 if (HasLeftBracket) {
204 if (S.empty() || S.front() != ']')
208 if (S.empty() || S.front() != '}')
213 // Found {vn}, {sn}, {an}, {v[n]}, {s[n]}, {a[n]}, {v[n:m]}, {s[n:m]}
215 Info.setAllowsRegister();
220 // \p Constraint will be left pointing at the last character of
221 // the constraint. In practice, it won't be changed unless the
222 // constraint is longer than one character.
223 std::string convertConstraint(const char *&Constraint) const override {
225 StringRef S(Constraint);
226 if (S == "DA" || S == "DB") {
227 return std::string("^") + std::string(Constraint++, 2);
230 const char *Begin = Constraint;
231 TargetInfo::ConstraintInfo Info("", "");
232 if (validateAsmConstraint(Constraint, Info))
233 return std::string(Begin).substr(0, Constraint - Begin + 1);
236 return std::string(1, *Constraint);
240 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
242 const std::vector<std::string> &FeatureVec) const override;
244 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
246 bool useFP16ConversionIntrinsics() const override { return false; }
248 void getTargetDefines(const LangOptions &Opts,
249 MacroBuilder &Builder) const override;
251 BuiltinVaListKind getBuiltinVaListKind() const override {
252 return TargetInfo::CharPtrBuiltinVaList;
255 bool isValidCPUName(StringRef Name) const override {
256 if (getTriple().getArch() == llvm::Triple::amdgcn)
257 return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
258 return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
261 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
263 bool setCPU(const std::string &Name) override {
264 if (getTriple().getArch() == llvm::Triple::amdgcn) {
265 GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
266 GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
268 GPUKind = llvm::AMDGPU::parseArchR600(Name);
269 GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
272 return GPUKind != llvm::AMDGPU::GK_NONE;
275 void setSupportedOpenCLOpts() override {
276 auto &Opts = getSupportedOpenCLOpts();
277 Opts.support("cl_clang_storage_class_specifiers");
278 Opts.support("cl_khr_icd");
280 bool IsAMDGCN = isAMDGCN(getTriple());
283 Opts.support("cl_khr_fp64");
285 if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
286 Opts.support("cl_khr_byte_addressable_store");
287 Opts.support("cl_khr_global_int32_base_atomics");
288 Opts.support("cl_khr_global_int32_extended_atomics");
289 Opts.support("cl_khr_local_int32_base_atomics");
290 Opts.support("cl_khr_local_int32_extended_atomics");
294 Opts.support("cl_khr_fp16");
295 Opts.support("cl_khr_int64_base_atomics");
296 Opts.support("cl_khr_int64_extended_atomics");
297 Opts.support("cl_khr_mipmap_image");
298 Opts.support("cl_khr_mipmap_image_writes");
299 Opts.support("cl_khr_subgroups");
300 Opts.support("cl_khr_3d_image_writes");
301 Opts.support("cl_amd_media_ops");
302 Opts.support("cl_amd_media_ops2");
306 LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
309 return LangAS::opencl_constant;
313 case OCLTK_ReserveID:
314 return LangAS::opencl_global;
317 return TargetInfo::getOpenCLTypeAddrSpace(TK);
321 LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
324 return LangAS::opencl_generic;
326 return LangAS::opencl_global;
328 return LangAS::opencl_local;
330 return LangAS::opencl_constant;
332 return LangAS::opencl_private;
334 return getLangASFromTargetAS(AS);
338 LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
339 return LangAS::Default;
342 llvm::Optional<LangAS> getConstantAddressSpace() const override {
343 return getLangASFromTargetAS(Constant);
346 /// \returns Target specific vtbl ptr address space.
347 unsigned getVtblPtrAddressSpace() const override {
348 return static_cast<unsigned>(Constant);
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.
355 /// \returns Otherwise return None and no conversion will be emitted in the
358 getDWARFAddressSpace(unsigned AddressSpace) const override {
359 const unsigned DWARF_Private = 1;
360 const unsigned DWARF_Local = 2;
361 if (AddressSpace == Private) {
362 return DWARF_Private;
363 } else if (AddressSpace == Local) {
370 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
375 case CC_OpenCLKernel:
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
383 uint64_t getNullPointerValue(LangAS AS) const override {
384 // FIXME: Also should handle region.
385 return (AS == LangAS::opencl_local || AS == LangAS::opencl_private)
389 void setAuxTarget(const TargetInfo *Aux) override;
391 bool hasExtIntType() const override { return true; }
394 } // namespace targets
397 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H