10b57cec5SDimitry Andric //===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===// 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 implements NVPTX TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "NVPTX.h" 140b57cec5SDimitry Andric #include "Targets.h" 150b57cec5SDimitry Andric #include "clang/Basic/Builtins.h" 160b57cec5SDimitry Andric #include "clang/Basic/MacroBuilder.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetBuiltins.h" 180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace clang; 210b57cec5SDimitry Andric using namespace clang::targets; 220b57cec5SDimitry Andric 23bdd1243dSDimitry Andric static constexpr Builtin::Info BuiltinInfo[] = { 240b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS) \ 25bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 260b57cec5SDimitry Andric #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 27bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, 280b57cec5SDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 29bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 300b57cec5SDimitry Andric #include "clang/Basic/BuiltinsNVPTX.def" 310b57cec5SDimitry Andric }; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple, 360b57cec5SDimitry Andric const TargetOptions &Opts, 370b57cec5SDimitry Andric unsigned TargetPointerWidth) 380b57cec5SDimitry Andric : TargetInfo(Triple) { 390b57cec5SDimitry Andric assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) && 400b57cec5SDimitry Andric "NVPTX only supports 32- and 64-bit modes."); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric PTXVersion = 32; 430b57cec5SDimitry Andric for (const StringRef Feature : Opts.FeaturesAsWritten) { 44bdd1243dSDimitry Andric int PTXV; 455f757f3fSDimitry Andric if (!Feature.starts_with("+ptx") || 46bdd1243dSDimitry Andric Feature.drop_front(4).getAsInteger(10, PTXV)) 470b57cec5SDimitry Andric continue; 48bdd1243dSDimitry Andric PTXVersion = PTXV; // TODO: should it be max(PTXVersion, PTXV)? 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric TLSSupported = false; 520b57cec5SDimitry Andric VLASupported = false; 530b57cec5SDimitry Andric AddrSpaceMap = &NVPTXAddrSpaceMap; 540b57cec5SDimitry Andric UseAddrSpaceMapMangling = true; 55bdd1243dSDimitry Andric // __bf16 is always available as a load/store only type. 56bdd1243dSDimitry Andric BFloat16Width = BFloat16Align = 16; 57bdd1243dSDimitry Andric BFloat16Format = &llvm::APFloat::BFloat(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Define available target features 600b57cec5SDimitry Andric // These must be defined in sorted order! 610b57cec5SDimitry Andric NoAsmVariants = true; 62*0fca6ea1SDimitry Andric GPU = OffloadArch::UNUSED; 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric // PTX supports f16 as a fundamental type. 65*0fca6ea1SDimitry Andric HasLegalHalfType = true; 66*0fca6ea1SDimitry Andric HasFloat16 = true; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric if (TargetPointerWidth == 32) 690b57cec5SDimitry Andric resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 700b57cec5SDimitry Andric else if (Opts.NVPTXUseShortPointers) 710b57cec5SDimitry Andric resetDataLayout( 720b57cec5SDimitry Andric "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 730b57cec5SDimitry Andric else 740b57cec5SDimitry Andric resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // If possible, get a TargetInfo for our host triple, so we can match its 770b57cec5SDimitry Andric // types. 780b57cec5SDimitry Andric llvm::Triple HostTriple(Opts.HostTriple); 790b57cec5SDimitry Andric if (!HostTriple.isNVPTX()) 8006c3fb27SDimitry Andric HostTarget = AllocateTarget(llvm::Triple(Opts.HostTriple), Opts); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // If no host target, make some guesses about the data layout and return. 830b57cec5SDimitry Andric if (!HostTarget) { 840b57cec5SDimitry Andric LongWidth = LongAlign = TargetPointerWidth; 850b57cec5SDimitry Andric PointerWidth = PointerAlign = TargetPointerWidth; 860b57cec5SDimitry Andric switch (TargetPointerWidth) { 870b57cec5SDimitry Andric case 32: 880b57cec5SDimitry Andric SizeType = TargetInfo::UnsignedInt; 890b57cec5SDimitry Andric PtrDiffType = TargetInfo::SignedInt; 900b57cec5SDimitry Andric IntPtrType = TargetInfo::SignedInt; 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric case 64: 930b57cec5SDimitry Andric SizeType = TargetInfo::UnsignedLong; 940b57cec5SDimitry Andric PtrDiffType = TargetInfo::SignedLong; 950b57cec5SDimitry Andric IntPtrType = TargetInfo::SignedLong; 960b57cec5SDimitry Andric break; 970b57cec5SDimitry Andric default: 980b57cec5SDimitry Andric llvm_unreachable("TargetPointerWidth must be 32 or 64"); 990b57cec5SDimitry Andric } 10006c3fb27SDimitry Andric 10106c3fb27SDimitry Andric MaxAtomicInlineWidth = TargetPointerWidth; 1020b57cec5SDimitry Andric return; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Copy properties from host target. 106bdd1243dSDimitry Andric PointerWidth = HostTarget->getPointerWidth(LangAS::Default); 107bdd1243dSDimitry Andric PointerAlign = HostTarget->getPointerAlign(LangAS::Default); 1080b57cec5SDimitry Andric BoolWidth = HostTarget->getBoolWidth(); 1090b57cec5SDimitry Andric BoolAlign = HostTarget->getBoolAlign(); 1100b57cec5SDimitry Andric IntWidth = HostTarget->getIntWidth(); 1110b57cec5SDimitry Andric IntAlign = HostTarget->getIntAlign(); 1120b57cec5SDimitry Andric HalfWidth = HostTarget->getHalfWidth(); 1130b57cec5SDimitry Andric HalfAlign = HostTarget->getHalfAlign(); 1140b57cec5SDimitry Andric FloatWidth = HostTarget->getFloatWidth(); 1150b57cec5SDimitry Andric FloatAlign = HostTarget->getFloatAlign(); 1160b57cec5SDimitry Andric DoubleWidth = HostTarget->getDoubleWidth(); 1170b57cec5SDimitry Andric DoubleAlign = HostTarget->getDoubleAlign(); 1180b57cec5SDimitry Andric LongWidth = HostTarget->getLongWidth(); 1190b57cec5SDimitry Andric LongAlign = HostTarget->getLongAlign(); 1200b57cec5SDimitry Andric LongLongWidth = HostTarget->getLongLongWidth(); 1210b57cec5SDimitry Andric LongLongAlign = HostTarget->getLongLongAlign(); 122*0fca6ea1SDimitry Andric MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0, 123*0fca6ea1SDimitry Andric /* HasNonWeakDef = */ true); 1240b57cec5SDimitry Andric NewAlign = HostTarget->getNewAlign(); 1250b57cec5SDimitry Andric DefaultAlignForAttributeAligned = 1260b57cec5SDimitry Andric HostTarget->getDefaultAlignForAttributeAligned(); 1270b57cec5SDimitry Andric SizeType = HostTarget->getSizeType(); 1280b57cec5SDimitry Andric IntMaxType = HostTarget->getIntMaxType(); 129bdd1243dSDimitry Andric PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default); 1300b57cec5SDimitry Andric IntPtrType = HostTarget->getIntPtrType(); 1310b57cec5SDimitry Andric WCharType = HostTarget->getWCharType(); 1320b57cec5SDimitry Andric WIntType = HostTarget->getWIntType(); 1330b57cec5SDimitry Andric Char16Type = HostTarget->getChar16Type(); 1340b57cec5SDimitry Andric Char32Type = HostTarget->getChar32Type(); 1350b57cec5SDimitry Andric Int64Type = HostTarget->getInt64Type(); 1360b57cec5SDimitry Andric SigAtomicType = HostTarget->getSigAtomicType(); 1370b57cec5SDimitry Andric ProcessIDType = HostTarget->getProcessIDType(); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment(); 1400b57cec5SDimitry Andric UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment(); 1410b57cec5SDimitry Andric UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment(); 1420b57cec5SDimitry Andric ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary(); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and 1450b57cec5SDimitry Andric // we need those macros to be identical on host and device, because (among 1460b57cec5SDimitry Andric // other things) they affect which standard library classes are defined, and 1470b57cec5SDimitry Andric // we need all classes to be defined on both the host and device. 1480b57cec5SDimitry Andric MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth(); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // Properties intentionally not copied from host: 1510b57cec5SDimitry Andric // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the 1520b57cec5SDimitry Andric // host/device boundary. 1530b57cec5SDimitry Andric // - SuitableAlign: Not visible across the host/device boundary, and may 1540b57cec5SDimitry Andric // correctly be different on host/device, e.g. if host has wider vector 1550b57cec5SDimitry Andric // types than device. 1560b57cec5SDimitry Andric // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same 1570b57cec5SDimitry Andric // as its double type, but that's not necessarily true on the host. 1580b57cec5SDimitry Andric // TODO: nvcc emits a warning when using long double on device; we should 1590b57cec5SDimitry Andric // do the same. 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const { 163bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric bool NVPTXTargetInfo::hasFeature(StringRef Feature) const { 1670b57cec5SDimitry Andric return llvm::StringSwitch<bool>(Feature) 1680b57cec5SDimitry Andric .Cases("ptx", "nvptx", true) 1690b57cec5SDimitry Andric .Default(false); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, 1730b57cec5SDimitry Andric MacroBuilder &Builder) const { 1740b57cec5SDimitry Andric Builder.defineMacro("__PTX__"); 1750b57cec5SDimitry Andric Builder.defineMacro("__NVPTX__"); 176*0fca6ea1SDimitry Andric 177*0fca6ea1SDimitry Andric // Skip setting architecture dependent macros if undefined. 178*0fca6ea1SDimitry Andric if (GPU == OffloadArch::UNUSED && !HostTarget) 179*0fca6ea1SDimitry Andric return; 180*0fca6ea1SDimitry Andric 18106c3fb27SDimitry Andric if (Opts.CUDAIsDevice || Opts.OpenMPIsTargetDevice || !HostTarget) { 1820b57cec5SDimitry Andric // Set __CUDA_ARCH__ for the GPU specified. 1830b57cec5SDimitry Andric std::string CUDAArchCode = [this] { 1840b57cec5SDimitry Andric switch (GPU) { 185*0fca6ea1SDimitry Andric case OffloadArch::GFX600: 186*0fca6ea1SDimitry Andric case OffloadArch::GFX601: 187*0fca6ea1SDimitry Andric case OffloadArch::GFX602: 188*0fca6ea1SDimitry Andric case OffloadArch::GFX700: 189*0fca6ea1SDimitry Andric case OffloadArch::GFX701: 190*0fca6ea1SDimitry Andric case OffloadArch::GFX702: 191*0fca6ea1SDimitry Andric case OffloadArch::GFX703: 192*0fca6ea1SDimitry Andric case OffloadArch::GFX704: 193*0fca6ea1SDimitry Andric case OffloadArch::GFX705: 194*0fca6ea1SDimitry Andric case OffloadArch::GFX801: 195*0fca6ea1SDimitry Andric case OffloadArch::GFX802: 196*0fca6ea1SDimitry Andric case OffloadArch::GFX803: 197*0fca6ea1SDimitry Andric case OffloadArch::GFX805: 198*0fca6ea1SDimitry Andric case OffloadArch::GFX810: 199*0fca6ea1SDimitry Andric case OffloadArch::GFX9_GENERIC: 200*0fca6ea1SDimitry Andric case OffloadArch::GFX900: 201*0fca6ea1SDimitry Andric case OffloadArch::GFX902: 202*0fca6ea1SDimitry Andric case OffloadArch::GFX904: 203*0fca6ea1SDimitry Andric case OffloadArch::GFX906: 204*0fca6ea1SDimitry Andric case OffloadArch::GFX908: 205*0fca6ea1SDimitry Andric case OffloadArch::GFX909: 206*0fca6ea1SDimitry Andric case OffloadArch::GFX90a: 207*0fca6ea1SDimitry Andric case OffloadArch::GFX90c: 208*0fca6ea1SDimitry Andric case OffloadArch::GFX940: 209*0fca6ea1SDimitry Andric case OffloadArch::GFX941: 210*0fca6ea1SDimitry Andric case OffloadArch::GFX942: 211*0fca6ea1SDimitry Andric case OffloadArch::GFX10_1_GENERIC: 212*0fca6ea1SDimitry Andric case OffloadArch::GFX1010: 213*0fca6ea1SDimitry Andric case OffloadArch::GFX1011: 214*0fca6ea1SDimitry Andric case OffloadArch::GFX1012: 215*0fca6ea1SDimitry Andric case OffloadArch::GFX1013: 216*0fca6ea1SDimitry Andric case OffloadArch::GFX10_3_GENERIC: 217*0fca6ea1SDimitry Andric case OffloadArch::GFX1030: 218*0fca6ea1SDimitry Andric case OffloadArch::GFX1031: 219*0fca6ea1SDimitry Andric case OffloadArch::GFX1032: 220*0fca6ea1SDimitry Andric case OffloadArch::GFX1033: 221*0fca6ea1SDimitry Andric case OffloadArch::GFX1034: 222*0fca6ea1SDimitry Andric case OffloadArch::GFX1035: 223*0fca6ea1SDimitry Andric case OffloadArch::GFX1036: 224*0fca6ea1SDimitry Andric case OffloadArch::GFX11_GENERIC: 225*0fca6ea1SDimitry Andric case OffloadArch::GFX1100: 226*0fca6ea1SDimitry Andric case OffloadArch::GFX1101: 227*0fca6ea1SDimitry Andric case OffloadArch::GFX1102: 228*0fca6ea1SDimitry Andric case OffloadArch::GFX1103: 229*0fca6ea1SDimitry Andric case OffloadArch::GFX1150: 230*0fca6ea1SDimitry Andric case OffloadArch::GFX1151: 231*0fca6ea1SDimitry Andric case OffloadArch::GFX1152: 232*0fca6ea1SDimitry Andric case OffloadArch::GFX12_GENERIC: 233*0fca6ea1SDimitry Andric case OffloadArch::GFX1200: 234*0fca6ea1SDimitry Andric case OffloadArch::GFX1201: 235*0fca6ea1SDimitry Andric case OffloadArch::AMDGCNSPIRV: 236*0fca6ea1SDimitry Andric case OffloadArch::Generic: 237*0fca6ea1SDimitry Andric case OffloadArch::LAST: 2380b57cec5SDimitry Andric break; 239*0fca6ea1SDimitry Andric case OffloadArch::UNKNOWN: 2400b57cec5SDimitry Andric assert(false && "No GPU arch when compiling CUDA device code."); 2410b57cec5SDimitry Andric return ""; 242*0fca6ea1SDimitry Andric case OffloadArch::UNUSED: 243*0fca6ea1SDimitry Andric case OffloadArch::SM_20: 2440b57cec5SDimitry Andric return "200"; 245*0fca6ea1SDimitry Andric case OffloadArch::SM_21: 2460b57cec5SDimitry Andric return "210"; 247*0fca6ea1SDimitry Andric case OffloadArch::SM_30: 2480b57cec5SDimitry Andric return "300"; 249*0fca6ea1SDimitry Andric case OffloadArch::SM_32_: 2500b57cec5SDimitry Andric return "320"; 251*0fca6ea1SDimitry Andric case OffloadArch::SM_35: 2520b57cec5SDimitry Andric return "350"; 253*0fca6ea1SDimitry Andric case OffloadArch::SM_37: 2540b57cec5SDimitry Andric return "370"; 255*0fca6ea1SDimitry Andric case OffloadArch::SM_50: 2560b57cec5SDimitry Andric return "500"; 257*0fca6ea1SDimitry Andric case OffloadArch::SM_52: 2580b57cec5SDimitry Andric return "520"; 259*0fca6ea1SDimitry Andric case OffloadArch::SM_53: 2600b57cec5SDimitry Andric return "530"; 261*0fca6ea1SDimitry Andric case OffloadArch::SM_60: 2620b57cec5SDimitry Andric return "600"; 263*0fca6ea1SDimitry Andric case OffloadArch::SM_61: 2640b57cec5SDimitry Andric return "610"; 265*0fca6ea1SDimitry Andric case OffloadArch::SM_62: 2660b57cec5SDimitry Andric return "620"; 267*0fca6ea1SDimitry Andric case OffloadArch::SM_70: 2680b57cec5SDimitry Andric return "700"; 269*0fca6ea1SDimitry Andric case OffloadArch::SM_72: 2700b57cec5SDimitry Andric return "720"; 271*0fca6ea1SDimitry Andric case OffloadArch::SM_75: 2720b57cec5SDimitry Andric return "750"; 273*0fca6ea1SDimitry Andric case OffloadArch::SM_80: 2745ffd83dbSDimitry Andric return "800"; 275*0fca6ea1SDimitry Andric case OffloadArch::SM_86: 276fe6060f1SDimitry Andric return "860"; 277*0fca6ea1SDimitry Andric case OffloadArch::SM_87: 278bdd1243dSDimitry Andric return "870"; 279*0fca6ea1SDimitry Andric case OffloadArch::SM_89: 280bdd1243dSDimitry Andric return "890"; 281*0fca6ea1SDimitry Andric case OffloadArch::SM_90: 282*0fca6ea1SDimitry Andric case OffloadArch::SM_90a: 283bdd1243dSDimitry Andric return "900"; 2840b57cec5SDimitry Andric } 285*0fca6ea1SDimitry Andric llvm_unreachable("unhandled OffloadArch"); 2860b57cec5SDimitry Andric }(); 2870b57cec5SDimitry Andric Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); 288*0fca6ea1SDimitry Andric if (GPU == OffloadArch::SM_90a) 2895f757f3fSDimitry Andric Builder.defineMacro("__CUDA_ARCH_FEAT_SM90_ALL", "1"); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const { 294bdd1243dSDimitry Andric return llvm::ArrayRef(BuiltinInfo, 295bdd1243dSDimitry Andric clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin); 2960b57cec5SDimitry Andric } 297