xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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