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