1e5dd7070Spatrick //===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements NVPTX TargetInfo objects.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "NVPTX.h"
14e5dd7070Spatrick #include "Targets.h"
15e5dd7070Spatrick #include "clang/Basic/Builtins.h"
16e5dd7070Spatrick #include "clang/Basic/MacroBuilder.h"
17e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h"
18e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
19e5dd7070Spatrick
20e5dd7070Spatrick using namespace clang;
21e5dd7070Spatrick using namespace clang::targets;
22e5dd7070Spatrick
23*12c85518Srobert static constexpr Builtin::Info BuiltinInfo[] = {
24e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS) \
25*12c85518Srobert {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
27*12c85518Srobert {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
28e5dd7070Spatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
29*12c85518Srobert {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
30e5dd7070Spatrick #include "clang/Basic/BuiltinsNVPTX.def"
31e5dd7070Spatrick };
32e5dd7070Spatrick
33e5dd7070Spatrick const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
34e5dd7070Spatrick
NVPTXTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts,unsigned TargetPointerWidth)35e5dd7070Spatrick NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
36e5dd7070Spatrick const TargetOptions &Opts,
37e5dd7070Spatrick unsigned TargetPointerWidth)
38e5dd7070Spatrick : TargetInfo(Triple) {
39e5dd7070Spatrick assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
40e5dd7070Spatrick "NVPTX only supports 32- and 64-bit modes.");
41e5dd7070Spatrick
42e5dd7070Spatrick PTXVersion = 32;
43e5dd7070Spatrick for (const StringRef Feature : Opts.FeaturesAsWritten) {
44*12c85518Srobert int PTXV;
45*12c85518Srobert if (!Feature.startswith("+ptx") ||
46*12c85518Srobert Feature.drop_front(4).getAsInteger(10, PTXV))
47e5dd7070Spatrick continue;
48*12c85518Srobert PTXVersion = PTXV; // TODO: should it be max(PTXVersion, PTXV)?
49e5dd7070Spatrick }
50e5dd7070Spatrick
51e5dd7070Spatrick TLSSupported = false;
52e5dd7070Spatrick VLASupported = false;
53e5dd7070Spatrick AddrSpaceMap = &NVPTXAddrSpaceMap;
54e5dd7070Spatrick UseAddrSpaceMapMangling = true;
55*12c85518Srobert // __bf16 is always available as a load/store only type.
56*12c85518Srobert BFloat16Width = BFloat16Align = 16;
57*12c85518Srobert BFloat16Format = &llvm::APFloat::BFloat();
58e5dd7070Spatrick
59e5dd7070Spatrick // Define available target features
60e5dd7070Spatrick // These must be defined in sorted order!
61e5dd7070Spatrick NoAsmVariants = true;
62e5dd7070Spatrick GPU = CudaArch::SM_20;
63e5dd7070Spatrick
64e5dd7070Spatrick if (TargetPointerWidth == 32)
65e5dd7070Spatrick resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
66e5dd7070Spatrick else if (Opts.NVPTXUseShortPointers)
67e5dd7070Spatrick resetDataLayout(
68e5dd7070Spatrick "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
69e5dd7070Spatrick else
70e5dd7070Spatrick resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
71e5dd7070Spatrick
72e5dd7070Spatrick // If possible, get a TargetInfo for our host triple, so we can match its
73e5dd7070Spatrick // types.
74e5dd7070Spatrick llvm::Triple HostTriple(Opts.HostTriple);
75e5dd7070Spatrick if (!HostTriple.isNVPTX())
76e5dd7070Spatrick HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
77e5dd7070Spatrick
78e5dd7070Spatrick // If no host target, make some guesses about the data layout and return.
79e5dd7070Spatrick if (!HostTarget) {
80e5dd7070Spatrick LongWidth = LongAlign = TargetPointerWidth;
81e5dd7070Spatrick PointerWidth = PointerAlign = TargetPointerWidth;
82e5dd7070Spatrick switch (TargetPointerWidth) {
83e5dd7070Spatrick case 32:
84e5dd7070Spatrick SizeType = TargetInfo::UnsignedInt;
85e5dd7070Spatrick PtrDiffType = TargetInfo::SignedInt;
86e5dd7070Spatrick IntPtrType = TargetInfo::SignedInt;
87e5dd7070Spatrick break;
88e5dd7070Spatrick case 64:
89e5dd7070Spatrick SizeType = TargetInfo::UnsignedLong;
90e5dd7070Spatrick PtrDiffType = TargetInfo::SignedLong;
91e5dd7070Spatrick IntPtrType = TargetInfo::SignedLong;
92e5dd7070Spatrick break;
93e5dd7070Spatrick default:
94e5dd7070Spatrick llvm_unreachable("TargetPointerWidth must be 32 or 64");
95e5dd7070Spatrick }
96e5dd7070Spatrick return;
97e5dd7070Spatrick }
98e5dd7070Spatrick
99e5dd7070Spatrick // Copy properties from host target.
100*12c85518Srobert PointerWidth = HostTarget->getPointerWidth(LangAS::Default);
101*12c85518Srobert PointerAlign = HostTarget->getPointerAlign(LangAS::Default);
102e5dd7070Spatrick BoolWidth = HostTarget->getBoolWidth();
103e5dd7070Spatrick BoolAlign = HostTarget->getBoolAlign();
104e5dd7070Spatrick IntWidth = HostTarget->getIntWidth();
105e5dd7070Spatrick IntAlign = HostTarget->getIntAlign();
106e5dd7070Spatrick HalfWidth = HostTarget->getHalfWidth();
107e5dd7070Spatrick HalfAlign = HostTarget->getHalfAlign();
108e5dd7070Spatrick FloatWidth = HostTarget->getFloatWidth();
109e5dd7070Spatrick FloatAlign = HostTarget->getFloatAlign();
110e5dd7070Spatrick DoubleWidth = HostTarget->getDoubleWidth();
111e5dd7070Spatrick DoubleAlign = HostTarget->getDoubleAlign();
112e5dd7070Spatrick LongWidth = HostTarget->getLongWidth();
113e5dd7070Spatrick LongAlign = HostTarget->getLongAlign();
114e5dd7070Spatrick LongLongWidth = HostTarget->getLongLongWidth();
115e5dd7070Spatrick LongLongAlign = HostTarget->getLongLongAlign();
116e5dd7070Spatrick MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0);
117e5dd7070Spatrick NewAlign = HostTarget->getNewAlign();
118e5dd7070Spatrick DefaultAlignForAttributeAligned =
119e5dd7070Spatrick HostTarget->getDefaultAlignForAttributeAligned();
120e5dd7070Spatrick SizeType = HostTarget->getSizeType();
121e5dd7070Spatrick IntMaxType = HostTarget->getIntMaxType();
122*12c85518Srobert PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default);
123e5dd7070Spatrick IntPtrType = HostTarget->getIntPtrType();
124e5dd7070Spatrick WCharType = HostTarget->getWCharType();
125e5dd7070Spatrick WIntType = HostTarget->getWIntType();
126e5dd7070Spatrick Char16Type = HostTarget->getChar16Type();
127e5dd7070Spatrick Char32Type = HostTarget->getChar32Type();
128e5dd7070Spatrick Int64Type = HostTarget->getInt64Type();
129e5dd7070Spatrick SigAtomicType = HostTarget->getSigAtomicType();
130e5dd7070Spatrick ProcessIDType = HostTarget->getProcessIDType();
131e5dd7070Spatrick
132e5dd7070Spatrick UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
133e5dd7070Spatrick UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
134e5dd7070Spatrick UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
135e5dd7070Spatrick ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
136e5dd7070Spatrick
137e5dd7070Spatrick // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
138e5dd7070Spatrick // we need those macros to be identical on host and device, because (among
139e5dd7070Spatrick // other things) they affect which standard library classes are defined, and
140e5dd7070Spatrick // we need all classes to be defined on both the host and device.
141e5dd7070Spatrick MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
142e5dd7070Spatrick
143e5dd7070Spatrick // Properties intentionally not copied from host:
144e5dd7070Spatrick // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
145e5dd7070Spatrick // host/device boundary.
146e5dd7070Spatrick // - SuitableAlign: Not visible across the host/device boundary, and may
147e5dd7070Spatrick // correctly be different on host/device, e.g. if host has wider vector
148e5dd7070Spatrick // types than device.
149e5dd7070Spatrick // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
150e5dd7070Spatrick // as its double type, but that's not necessarily true on the host.
151e5dd7070Spatrick // TODO: nvcc emits a warning when using long double on device; we should
152e5dd7070Spatrick // do the same.
153e5dd7070Spatrick }
154e5dd7070Spatrick
getGCCRegNames() const155e5dd7070Spatrick ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
156*12c85518Srobert return llvm::ArrayRef(GCCRegNames);
157e5dd7070Spatrick }
158e5dd7070Spatrick
hasFeature(StringRef Feature) const159e5dd7070Spatrick bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
160e5dd7070Spatrick return llvm::StringSwitch<bool>(Feature)
161e5dd7070Spatrick .Cases("ptx", "nvptx", true)
162e5dd7070Spatrick .Default(false);
163e5dd7070Spatrick }
164e5dd7070Spatrick
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const165e5dd7070Spatrick void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
166e5dd7070Spatrick MacroBuilder &Builder) const {
167e5dd7070Spatrick Builder.defineMacro("__PTX__");
168e5dd7070Spatrick Builder.defineMacro("__NVPTX__");
169*12c85518Srobert if (Opts.CUDAIsDevice || Opts.OpenMPIsDevice) {
170e5dd7070Spatrick // Set __CUDA_ARCH__ for the GPU specified.
171e5dd7070Spatrick std::string CUDAArchCode = [this] {
172e5dd7070Spatrick switch (GPU) {
173e5dd7070Spatrick case CudaArch::GFX600:
174e5dd7070Spatrick case CudaArch::GFX601:
175a9ac8606Spatrick case CudaArch::GFX602:
176e5dd7070Spatrick case CudaArch::GFX700:
177e5dd7070Spatrick case CudaArch::GFX701:
178e5dd7070Spatrick case CudaArch::GFX702:
179e5dd7070Spatrick case CudaArch::GFX703:
180e5dd7070Spatrick case CudaArch::GFX704:
181a9ac8606Spatrick case CudaArch::GFX705:
182e5dd7070Spatrick case CudaArch::GFX801:
183e5dd7070Spatrick case CudaArch::GFX802:
184e5dd7070Spatrick case CudaArch::GFX803:
185a9ac8606Spatrick case CudaArch::GFX805:
186e5dd7070Spatrick case CudaArch::GFX810:
187e5dd7070Spatrick case CudaArch::GFX900:
188e5dd7070Spatrick case CudaArch::GFX902:
189e5dd7070Spatrick case CudaArch::GFX904:
190e5dd7070Spatrick case CudaArch::GFX906:
191e5dd7070Spatrick case CudaArch::GFX908:
192e5dd7070Spatrick case CudaArch::GFX909:
193a9ac8606Spatrick case CudaArch::GFX90a:
194a9ac8606Spatrick case CudaArch::GFX90c:
195*12c85518Srobert case CudaArch::GFX940:
196e5dd7070Spatrick case CudaArch::GFX1010:
197e5dd7070Spatrick case CudaArch::GFX1011:
198e5dd7070Spatrick case CudaArch::GFX1012:
199a9ac8606Spatrick case CudaArch::GFX1013:
200ec727ea7Spatrick case CudaArch::GFX1030:
201a9ac8606Spatrick case CudaArch::GFX1031:
202a9ac8606Spatrick case CudaArch::GFX1032:
203a9ac8606Spatrick case CudaArch::GFX1033:
204a9ac8606Spatrick case CudaArch::GFX1034:
205a9ac8606Spatrick case CudaArch::GFX1035:
206*12c85518Srobert case CudaArch::GFX1036:
207*12c85518Srobert case CudaArch::GFX1100:
208*12c85518Srobert case CudaArch::GFX1101:
209*12c85518Srobert case CudaArch::GFX1102:
210*12c85518Srobert case CudaArch::GFX1103:
211*12c85518Srobert case CudaArch::Generic:
212e5dd7070Spatrick case CudaArch::LAST:
213e5dd7070Spatrick break;
214a9ac8606Spatrick case CudaArch::UNUSED:
215e5dd7070Spatrick case CudaArch::UNKNOWN:
216e5dd7070Spatrick assert(false && "No GPU arch when compiling CUDA device code.");
217e5dd7070Spatrick return "";
218e5dd7070Spatrick case CudaArch::SM_20:
219e5dd7070Spatrick return "200";
220e5dd7070Spatrick case CudaArch::SM_21:
221e5dd7070Spatrick return "210";
222e5dd7070Spatrick case CudaArch::SM_30:
223e5dd7070Spatrick return "300";
224e5dd7070Spatrick case CudaArch::SM_32:
225e5dd7070Spatrick return "320";
226e5dd7070Spatrick case CudaArch::SM_35:
227e5dd7070Spatrick return "350";
228e5dd7070Spatrick case CudaArch::SM_37:
229e5dd7070Spatrick return "370";
230e5dd7070Spatrick case CudaArch::SM_50:
231e5dd7070Spatrick return "500";
232e5dd7070Spatrick case CudaArch::SM_52:
233e5dd7070Spatrick return "520";
234e5dd7070Spatrick case CudaArch::SM_53:
235e5dd7070Spatrick return "530";
236e5dd7070Spatrick case CudaArch::SM_60:
237e5dd7070Spatrick return "600";
238e5dd7070Spatrick case CudaArch::SM_61:
239e5dd7070Spatrick return "610";
240e5dd7070Spatrick case CudaArch::SM_62:
241e5dd7070Spatrick return "620";
242e5dd7070Spatrick case CudaArch::SM_70:
243e5dd7070Spatrick return "700";
244e5dd7070Spatrick case CudaArch::SM_72:
245e5dd7070Spatrick return "720";
246e5dd7070Spatrick case CudaArch::SM_75:
247e5dd7070Spatrick return "750";
248ec727ea7Spatrick case CudaArch::SM_80:
249ec727ea7Spatrick return "800";
250a9ac8606Spatrick case CudaArch::SM_86:
251a9ac8606Spatrick return "860";
252*12c85518Srobert case CudaArch::SM_87:
253*12c85518Srobert return "870";
254*12c85518Srobert case CudaArch::SM_89:
255*12c85518Srobert return "890";
256*12c85518Srobert case CudaArch::SM_90:
257*12c85518Srobert return "900";
258e5dd7070Spatrick }
259e5dd7070Spatrick llvm_unreachable("unhandled CudaArch");
260e5dd7070Spatrick }();
261e5dd7070Spatrick Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
262e5dd7070Spatrick }
263e5dd7070Spatrick }
264e5dd7070Spatrick
getTargetBuiltins() const265e5dd7070Spatrick ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
266*12c85518Srobert return llvm::ArrayRef(BuiltinInfo,
267*12c85518Srobert clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);
268e5dd7070Spatrick }
269