xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares AMDGPU TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
150b57cec5SDimitry Andric 
16e8d8bef9SDimitry Andric #include "clang/Basic/TargetID.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
180b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
205f757f3fSDimitry Andric #include "llvm/Support/AMDGPUAddrSpace.h"
210b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
2206c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h"
2306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
24bdd1243dSDimitry Andric #include <optional>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace clang {
270b57cec5SDimitry Andric namespace targets {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   static const char *const GCCRegNames[];
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   static const LangASMap AMDGPUDefIsGenMap;
340b57cec5SDimitry Andric   static const LangASMap AMDGPUDefIsPrivMap;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   llvm::AMDGPU::GPUKind GPUKind;
370b57cec5SDimitry Andric   unsigned GPUFeatures;
38e8d8bef9SDimitry Andric   unsigned WavefrontSize;
39e8d8bef9SDimitry Andric 
4006c3fb27SDimitry Andric   /// Whether to use cumode or WGP mode. True for cumode. False for WGP mode.
4106c3fb27SDimitry Andric   bool CUMode;
4206c3fb27SDimitry Andric 
4306c3fb27SDimitry Andric   /// Whether having image instructions.
4406c3fb27SDimitry Andric   bool HasImage = false;
4506c3fb27SDimitry Andric 
46e8d8bef9SDimitry Andric   /// Target ID is device name followed by optional feature name postfixed
47e8d8bef9SDimitry Andric   /// by plus or minus sign delimitted by colon, e.g. gfx908:xnack+:sramecc-.
48e8d8bef9SDimitry Andric   /// If the target ID contains feature+, map it to true.
49e8d8bef9SDimitry Andric   /// If the target ID contains feature-, map it to false.
50e8d8bef9SDimitry Andric   /// If the target ID does not contain a feature (default), do not map it.
51e8d8bef9SDimitry Andric   llvm::StringMap<bool> OffloadArchFeatures;
52e8d8bef9SDimitry Andric   std::string TargetID;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   bool hasFP64() const {
550b57cec5SDimitry Andric     return getTriple().getArch() == llvm::Triple::amdgcn ||
560b57cec5SDimitry Andric            !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64);
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   /// Has fast fma f32
600b57cec5SDimitry Andric   bool hasFastFMAF() const {
610b57cec5SDimitry Andric     return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   /// Has fast fma f64
650b57cec5SDimitry Andric   bool hasFastFMA() const {
660b57cec5SDimitry Andric     return getTriple().getArch() == llvm::Triple::amdgcn;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   bool hasFMAF() const {
700b57cec5SDimitry Andric     return getTriple().getArch() == llvm::Triple::amdgcn ||
710b57cec5SDimitry Andric            !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA);
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   bool hasFullRateDenormalsF32() const {
750b57cec5SDimitry Andric     return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   bool hasLDEXPF() const {
790b57cec5SDimitry Andric     return getTriple().getArch() == llvm::Triple::amdgcn ||
800b57cec5SDimitry Andric            !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP);
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   static bool isAMDGCN(const llvm::Triple &TT) {
840b57cec5SDimitry Andric     return TT.getArch() == llvm::Triple::amdgcn;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   static bool isR600(const llvm::Triple &TT) {
880b57cec5SDimitry Andric     return TT.getArch() == llvm::Triple::r600;
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric public:
920b57cec5SDimitry Andric   AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   void setAddressSpaceMap(bool DefaultIsPrivate);
950b57cec5SDimitry Andric 
96fe6060f1SDimitry Andric   void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
970b57cec5SDimitry Andric 
98bdd1243dSDimitry Andric   uint64_t getPointerWidthV(LangAS AS) const override {
990b57cec5SDimitry Andric     if (isR600(getTriple()))
1000b57cec5SDimitry Andric       return 32;
101bdd1243dSDimitry Andric     unsigned TargetAS = getTargetAddressSpace(AS);
1020b57cec5SDimitry Andric 
1035f757f3fSDimitry Andric     if (TargetAS == llvm::AMDGPUAS::PRIVATE_ADDRESS ||
1045f757f3fSDimitry Andric         TargetAS == llvm::AMDGPUAS::LOCAL_ADDRESS)
1050b57cec5SDimitry Andric       return 32;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric     return 64;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
110bdd1243dSDimitry Andric   uint64_t getPointerAlignV(LangAS AddrSpace) const override {
1110b57cec5SDimitry Andric     return getPointerWidthV(AddrSpace);
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   uint64_t getMaxPointerWidth() const override {
1150b57cec5SDimitry Andric     return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
118bdd1243dSDimitry Andric   bool hasBFloat16Type() const override { return isAMDGCN(getTriple()); }
119bdd1243dSDimitry Andric 
12006c3fb27SDimitry Andric   std::string_view getClobbers() const override { return ""; }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   ArrayRef<const char *> getGCCRegNames() const override;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
125bdd1243dSDimitry Andric     return std::nullopt;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   /// Accepted register names: (n, m is unsigned integer, n < m)
1290b57cec5SDimitry Andric   /// v
1300b57cec5SDimitry Andric   /// s
1315ffd83dbSDimitry Andric   /// a
1320b57cec5SDimitry Andric   /// {vn}, {v[n]}
1330b57cec5SDimitry Andric   /// {sn}, {s[n]}
1345ffd83dbSDimitry Andric   /// {an}, {a[n]}
1350b57cec5SDimitry Andric   /// {S} , where S is a special register name
1360b57cec5SDimitry Andric   ////{v[n:m]}
1370b57cec5SDimitry Andric   /// {s[n:m]}
1385ffd83dbSDimitry Andric   /// {a[n:m]}
1390b57cec5SDimitry Andric   bool validateAsmConstraint(const char *&Name,
1400b57cec5SDimitry Andric                              TargetInfo::ConstraintInfo &Info) const override {
1410b57cec5SDimitry Andric     static const ::llvm::StringSet<> SpecialRegs({
1420b57cec5SDimitry Andric         "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
1430b57cec5SDimitry Andric         "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
1440b57cec5SDimitry Andric         "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
1450b57cec5SDimitry Andric     });
1460b57cec5SDimitry Andric 
1475ffd83dbSDimitry Andric     switch (*Name) {
1485ffd83dbSDimitry Andric     case 'I':
1495ffd83dbSDimitry Andric       Info.setRequiresImmediate(-16, 64);
1505ffd83dbSDimitry Andric       return true;
1515ffd83dbSDimitry Andric     case 'J':
1525ffd83dbSDimitry Andric       Info.setRequiresImmediate(-32768, 32767);
1535ffd83dbSDimitry Andric       return true;
1545ffd83dbSDimitry Andric     case 'A':
1555ffd83dbSDimitry Andric     case 'B':
1565ffd83dbSDimitry Andric     case 'C':
1575ffd83dbSDimitry Andric       Info.setRequiresImmediate();
1585ffd83dbSDimitry Andric       return true;
1595ffd83dbSDimitry Andric     default:
1605ffd83dbSDimitry Andric       break;
1615ffd83dbSDimitry Andric     }
1625ffd83dbSDimitry Andric 
1630b57cec5SDimitry Andric     StringRef S(Name);
1645ffd83dbSDimitry Andric 
1655ffd83dbSDimitry Andric     if (S == "DA" || S == "DB") {
1665ffd83dbSDimitry Andric       Name++;
1675ffd83dbSDimitry Andric       Info.setRequiresImmediate();
1685ffd83dbSDimitry Andric       return true;
1695ffd83dbSDimitry Andric     }
1705ffd83dbSDimitry Andric 
171*0fca6ea1SDimitry Andric     bool HasLeftParen = S.consume_front("{");
1720b57cec5SDimitry Andric     if (S.empty())
1730b57cec5SDimitry Andric       return false;
1745ffd83dbSDimitry Andric     if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
1750b57cec5SDimitry Andric       if (!HasLeftParen)
1760b57cec5SDimitry Andric         return false;
1770b57cec5SDimitry Andric       auto E = S.find('}');
1780b57cec5SDimitry Andric       if (!SpecialRegs.count(S.substr(0, E)))
1790b57cec5SDimitry Andric         return false;
1800b57cec5SDimitry Andric       S = S.drop_front(E + 1);
1810b57cec5SDimitry Andric       if (!S.empty())
1820b57cec5SDimitry Andric         return false;
1830b57cec5SDimitry Andric       // Found {S} where S is a special register.
1840b57cec5SDimitry Andric       Info.setAllowsRegister();
1850b57cec5SDimitry Andric       Name = S.data() - 1;
1860b57cec5SDimitry Andric       return true;
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric     S = S.drop_front();
1890b57cec5SDimitry Andric     if (!HasLeftParen) {
1900b57cec5SDimitry Andric       if (!S.empty())
1910b57cec5SDimitry Andric         return false;
1925ffd83dbSDimitry Andric       // Found s, v or a.
1930b57cec5SDimitry Andric       Info.setAllowsRegister();
1940b57cec5SDimitry Andric       Name = S.data() - 1;
1950b57cec5SDimitry Andric       return true;
1960b57cec5SDimitry Andric     }
197*0fca6ea1SDimitry Andric     bool HasLeftBracket = S.consume_front("[");
1980b57cec5SDimitry Andric     unsigned long long N;
1990b57cec5SDimitry Andric     if (S.empty() || consumeUnsignedInteger(S, 10, N))
2000b57cec5SDimitry Andric       return false;
2017a6dacacSDimitry Andric     if (S.consume_front(":")) {
2020b57cec5SDimitry Andric       if (!HasLeftBracket)
2030b57cec5SDimitry Andric         return false;
2040b57cec5SDimitry Andric       unsigned long long M;
2050b57cec5SDimitry Andric       if (consumeUnsignedInteger(S, 10, M) || N >= M)
2060b57cec5SDimitry Andric         return false;
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric     if (HasLeftBracket) {
2097a6dacacSDimitry Andric       if (!S.consume_front("]"))
2100b57cec5SDimitry Andric         return false;
2110b57cec5SDimitry Andric     }
2127a6dacacSDimitry Andric     if (!S.consume_front("}"))
2130b57cec5SDimitry Andric       return false;
2140b57cec5SDimitry Andric     if (!S.empty())
2150b57cec5SDimitry Andric       return false;
2165ffd83dbSDimitry Andric     // Found {vn}, {sn}, {an}, {v[n]}, {s[n]}, {a[n]}, {v[n:m]}, {s[n:m]}
2175ffd83dbSDimitry Andric     // or {a[n:m]}.
2180b57cec5SDimitry Andric     Info.setAllowsRegister();
2190b57cec5SDimitry Andric     Name = S.data() - 1;
2200b57cec5SDimitry Andric     return true;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   // \p Constraint will be left pointing at the last character of
2240b57cec5SDimitry Andric   // the constraint.  In practice, it won't be changed unless the
2250b57cec5SDimitry Andric   // constraint is longer than one character.
2260b57cec5SDimitry Andric   std::string convertConstraint(const char *&Constraint) const override {
2275ffd83dbSDimitry Andric 
2285ffd83dbSDimitry Andric     StringRef S(Constraint);
2295ffd83dbSDimitry Andric     if (S == "DA" || S == "DB") {
2305ffd83dbSDimitry Andric       return std::string("^") + std::string(Constraint++, 2);
2315ffd83dbSDimitry Andric     }
2325ffd83dbSDimitry Andric 
2330b57cec5SDimitry Andric     const char *Begin = Constraint;
2340b57cec5SDimitry Andric     TargetInfo::ConstraintInfo Info("", "");
2350b57cec5SDimitry Andric     if (validateAsmConstraint(Constraint, Info))
2360b57cec5SDimitry Andric       return std::string(Begin).substr(0, Constraint - Begin + 1);
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric     Constraint = Begin;
2390b57cec5SDimitry Andric     return std::string(1, *Constraint);
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   bool
2430b57cec5SDimitry Andric   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
2440b57cec5SDimitry Andric                  StringRef CPU,
2450b57cec5SDimitry Andric                  const std::vector<std::string> &FeatureVec) const override;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
2480b57cec5SDimitry Andric 
2495ffd83dbSDimitry Andric   bool useFP16ConversionIntrinsics() const override { return false; }
2505ffd83dbSDimitry Andric 
2510b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2520b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override {
2550b57cec5SDimitry Andric     return TargetInfo::CharPtrBuiltinVaList;
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override {
2590b57cec5SDimitry Andric     if (getTriple().getArch() == llvm::Triple::amdgcn)
2600b57cec5SDimitry Andric       return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
2610b57cec5SDimitry Andric     return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override {
2670b57cec5SDimitry Andric     if (getTriple().getArch() == llvm::Triple::amdgcn) {
2680b57cec5SDimitry Andric       GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
2690b57cec5SDimitry Andric       GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
2700b57cec5SDimitry Andric     } else {
2710b57cec5SDimitry Andric       GPUKind = llvm::AMDGPU::parseArchR600(Name);
2720b57cec5SDimitry Andric       GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric     return GPUKind != llvm::AMDGPU::GK_NONE;
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   void setSupportedOpenCLOpts() override {
2790b57cec5SDimitry Andric     auto &Opts = getSupportedOpenCLOpts();
280e8d8bef9SDimitry Andric     Opts["cl_clang_storage_class_specifiers"] = true;
281e8d8bef9SDimitry Andric     Opts["__cl_clang_variadic_functions"] = true;
282e8d8bef9SDimitry Andric     Opts["__cl_clang_function_pointers"] = true;
283fe6060f1SDimitry Andric     Opts["__cl_clang_non_portable_kernel_param_types"] = true;
284fe6060f1SDimitry Andric     Opts["__cl_clang_bitfields"] = true;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     bool IsAMDGCN = isAMDGCN(getTriple());
2870b57cec5SDimitry Andric 
288e8d8bef9SDimitry Andric     Opts["cl_khr_fp64"] = hasFP64();
289fe6060f1SDimitry Andric     Opts["__opencl_c_fp64"] = hasFP64();
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
292e8d8bef9SDimitry Andric       Opts["cl_khr_byte_addressable_store"] = true;
293e8d8bef9SDimitry Andric       Opts["cl_khr_global_int32_base_atomics"] = true;
294e8d8bef9SDimitry Andric       Opts["cl_khr_global_int32_extended_atomics"] = true;
295e8d8bef9SDimitry Andric       Opts["cl_khr_local_int32_base_atomics"] = true;
296e8d8bef9SDimitry Andric       Opts["cl_khr_local_int32_extended_atomics"] = true;
2970b57cec5SDimitry Andric     }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric     if (IsAMDGCN) {
300e8d8bef9SDimitry Andric       Opts["cl_khr_fp16"] = true;
301e8d8bef9SDimitry Andric       Opts["cl_khr_int64_base_atomics"] = true;
302e8d8bef9SDimitry Andric       Opts["cl_khr_int64_extended_atomics"] = true;
303e8d8bef9SDimitry Andric       Opts["cl_khr_mipmap_image"] = true;
304e8d8bef9SDimitry Andric       Opts["cl_khr_mipmap_image_writes"] = true;
305e8d8bef9SDimitry Andric       Opts["cl_khr_subgroups"] = true;
306e8d8bef9SDimitry Andric       Opts["cl_amd_media_ops"] = true;
307e8d8bef9SDimitry Andric       Opts["cl_amd_media_ops2"] = true;
3086e75b2fbSDimitry Andric 
3096e75b2fbSDimitry Andric       Opts["__opencl_c_images"] = true;
3106e75b2fbSDimitry Andric       Opts["__opencl_c_3d_image_writes"] = true;
3116e75b2fbSDimitry Andric       Opts["cl_khr_3d_image_writes"] = true;
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
3160b57cec5SDimitry Andric     switch (TK) {
3170b57cec5SDimitry Andric     case OCLTK_Image:
3180b57cec5SDimitry Andric       return LangAS::opencl_constant;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric     case OCLTK_ClkEvent:
3210b57cec5SDimitry Andric     case OCLTK_Queue:
3220b57cec5SDimitry Andric     case OCLTK_ReserveID:
3230b57cec5SDimitry Andric       return LangAS::opencl_global;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     default:
3260b57cec5SDimitry Andric       return TargetInfo::getOpenCLTypeAddrSpace(TK);
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric   }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
3310b57cec5SDimitry Andric     switch (AS) {
3320b57cec5SDimitry Andric     case 0:
3330b57cec5SDimitry Andric       return LangAS::opencl_generic;
3340b57cec5SDimitry Andric     case 1:
3350b57cec5SDimitry Andric       return LangAS::opencl_global;
3360b57cec5SDimitry Andric     case 3:
3370b57cec5SDimitry Andric       return LangAS::opencl_local;
3380b57cec5SDimitry Andric     case 4:
3390b57cec5SDimitry Andric       return LangAS::opencl_constant;
3400b57cec5SDimitry Andric     case 5:
3410b57cec5SDimitry Andric       return LangAS::opencl_private;
3420b57cec5SDimitry Andric     default:
3430b57cec5SDimitry Andric       return getLangASFromTargetAS(AS);
3440b57cec5SDimitry Andric     }
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
348349cc55cSDimitry Andric     switch (AS) {
349349cc55cSDimitry Andric     case 0:
3500b57cec5SDimitry Andric       return LangAS::Default;
351349cc55cSDimitry Andric     case 1:
352349cc55cSDimitry Andric       return LangAS::cuda_device;
353349cc55cSDimitry Andric     case 3:
354349cc55cSDimitry Andric       return LangAS::cuda_shared;
355349cc55cSDimitry Andric     case 4:
356349cc55cSDimitry Andric       return LangAS::cuda_constant;
357349cc55cSDimitry Andric     default:
358349cc55cSDimitry Andric       return getLangASFromTargetAS(AS);
359349cc55cSDimitry Andric     }
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
362bdd1243dSDimitry Andric   std::optional<LangAS> getConstantAddressSpace() const override {
3635f757f3fSDimitry Andric     return getLangASFromTargetAS(llvm::AMDGPUAS::CONSTANT_ADDRESS);
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric 
366349cc55cSDimitry Andric   const llvm::omp::GV &getGridValue() const override {
367349cc55cSDimitry Andric     switch (WavefrontSize) {
368349cc55cSDimitry Andric     case 32:
369349cc55cSDimitry Andric       return llvm::omp::getAMDGPUGridValues<32>();
370349cc55cSDimitry Andric     case 64:
371349cc55cSDimitry Andric       return llvm::omp::getAMDGPUGridValues<64>();
372349cc55cSDimitry Andric     default:
373349cc55cSDimitry Andric       llvm_unreachable("getGridValue not implemented for this wavesize");
374349cc55cSDimitry Andric     }
375349cc55cSDimitry Andric   }
376349cc55cSDimitry Andric 
3770b57cec5SDimitry Andric   /// \returns Target specific vtbl ptr address space.
3780b57cec5SDimitry Andric   unsigned getVtblPtrAddressSpace() const override {
3795f757f3fSDimitry Andric     return static_cast<unsigned>(llvm::AMDGPUAS::CONSTANT_ADDRESS);
3800b57cec5SDimitry Andric   }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   /// \returns If a target requires an address within a target specific address
3830b57cec5SDimitry Andric   /// space \p AddressSpace to be converted in order to be used, then return the
3840b57cec5SDimitry Andric   /// corresponding target specific DWARF address space.
3850b57cec5SDimitry Andric   ///
386bdd1243dSDimitry Andric   /// \returns Otherwise return std::nullopt and no conversion will be emitted
387bdd1243dSDimitry Andric   /// in the DWARF.
388bdd1243dSDimitry Andric   std::optional<unsigned>
3890b57cec5SDimitry Andric   getDWARFAddressSpace(unsigned AddressSpace) const override {
3900b57cec5SDimitry Andric     const unsigned DWARF_Private = 1;
3910b57cec5SDimitry Andric     const unsigned DWARF_Local = 2;
3925f757f3fSDimitry Andric     if (AddressSpace == llvm::AMDGPUAS::PRIVATE_ADDRESS) {
3930b57cec5SDimitry Andric       return DWARF_Private;
3945f757f3fSDimitry Andric     } else if (AddressSpace == llvm::AMDGPUAS::LOCAL_ADDRESS) {
3950b57cec5SDimitry Andric       return DWARF_Local;
3960b57cec5SDimitry Andric     } else {
397bdd1243dSDimitry Andric       return std::nullopt;
3980b57cec5SDimitry Andric     }
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
4020b57cec5SDimitry Andric     switch (CC) {
4030b57cec5SDimitry Andric     default:
4040b57cec5SDimitry Andric       return CCCR_Warning;
4050b57cec5SDimitry Andric     case CC_C:
4060b57cec5SDimitry Andric     case CC_OpenCLKernel:
40781ad6265SDimitry Andric     case CC_AMDGPUKernelCall:
4080b57cec5SDimitry Andric       return CCCR_OK;
4090b57cec5SDimitry Andric     }
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   // In amdgcn target the null pointer in global, constant, and generic
4130b57cec5SDimitry Andric   // address space has value 0 but in private and local address space has
4140b57cec5SDimitry Andric   // value ~0.
4150b57cec5SDimitry Andric   uint64_t getNullPointerValue(LangAS AS) const override {
4165ffd83dbSDimitry Andric     // FIXME: Also should handle region.
417*0fca6ea1SDimitry Andric     return (AS == LangAS::opencl_local || AS == LangAS::opencl_private ||
418*0fca6ea1SDimitry Andric             AS == LangAS::sycl_local || AS == LangAS::sycl_private)
419*0fca6ea1SDimitry Andric                ? ~0
420*0fca6ea1SDimitry Andric                : 0;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   void setAuxTarget(const TargetInfo *Aux) override;
4245ffd83dbSDimitry Andric 
4250eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
426e8d8bef9SDimitry Andric 
427e8d8bef9SDimitry Andric   // Record offload arch features since they are needed for defining the
428e8d8bef9SDimitry Andric   // pre-defined macros.
429e8d8bef9SDimitry Andric   bool handleTargetFeatures(std::vector<std::string> &Features,
430e8d8bef9SDimitry Andric                             DiagnosticsEngine &Diags) override {
431e8d8bef9SDimitry Andric     auto TargetIDFeatures =
432e8d8bef9SDimitry Andric         getAllPossibleTargetIDFeatures(getTriple(), getArchNameAMDGCN(GPUKind));
43381ad6265SDimitry Andric     for (const auto &F : Features) {
434e8d8bef9SDimitry Andric       assert(F.front() == '+' || F.front() == '-');
435e8d8bef9SDimitry Andric       if (F == "+wavefrontsize64")
436e8d8bef9SDimitry Andric         WavefrontSize = 64;
43706c3fb27SDimitry Andric       else if (F == "+cumode")
43806c3fb27SDimitry Andric         CUMode = true;
43906c3fb27SDimitry Andric       else if (F == "-cumode")
44006c3fb27SDimitry Andric         CUMode = false;
44106c3fb27SDimitry Andric       else if (F == "+image-insts")
44206c3fb27SDimitry Andric         HasImage = true;
443e8d8bef9SDimitry Andric       bool IsOn = F.front() == '+';
444e8d8bef9SDimitry Andric       StringRef Name = StringRef(F).drop_front();
445349cc55cSDimitry Andric       if (!llvm::is_contained(TargetIDFeatures, Name))
44681ad6265SDimitry Andric         continue;
44706c3fb27SDimitry Andric       assert(!OffloadArchFeatures.contains(Name));
448e8d8bef9SDimitry Andric       OffloadArchFeatures[Name] = IsOn;
44981ad6265SDimitry Andric     }
450e8d8bef9SDimitry Andric     return true;
451e8d8bef9SDimitry Andric   }
452e8d8bef9SDimitry Andric 
453bdd1243dSDimitry Andric   std::optional<std::string> getTargetID() const override {
454e8d8bef9SDimitry Andric     if (!isAMDGCN(getTriple()))
455bdd1243dSDimitry Andric       return std::nullopt;
456e8d8bef9SDimitry Andric     // When -target-cpu is not set, we assume generic code that it is valid
457e8d8bef9SDimitry Andric     // for all GPU and use an empty string as target ID to represent that.
458e8d8bef9SDimitry Andric     if (GPUKind == llvm::AMDGPU::GK_NONE)
459e8d8bef9SDimitry Andric       return std::string("");
460e8d8bef9SDimitry Andric     return getCanonicalTargetID(getArchNameAMDGCN(GPUKind),
461e8d8bef9SDimitry Andric                                 OffloadArchFeatures);
462e8d8bef9SDimitry Andric   }
46306c3fb27SDimitry Andric 
46406c3fb27SDimitry Andric   bool hasHIPImageSupport() const override { return HasImage; }
4650b57cec5SDimitry Andric };
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric } // namespace targets
4680b57cec5SDimitry Andric } // namespace clang
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
471