334 lines · cpp
1//===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements NVPTX TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#include "NVPTX.h"14#include "clang/Basic/Builtins.h"15#include "clang/Basic/MacroBuilder.h"16#include "clang/Basic/TargetBuiltins.h"17#include "llvm/ADT/StringSwitch.h"18 19using namespace clang;20using namespace clang::targets;21 22static constexpr int NumBuiltins =23 clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin;24 25#define GET_BUILTIN_STR_TABLE26#include "clang/Basic/BuiltinsNVPTX.inc"27#undef GET_BUILTIN_STR_TABLE28 29static constexpr Builtin::Info BuiltinInfos[] = {30#define GET_BUILTIN_INFOS31#include "clang/Basic/BuiltinsNVPTX.inc"32#undef GET_BUILTIN_INFOS33};34static_assert(std::size(BuiltinInfos) == NumBuiltins);35 36const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};37 38NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,39 const TargetOptions &Opts,40 unsigned TargetPointerWidth)41 : TargetInfo(Triple) {42 assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&43 "NVPTX only supports 32- and 64-bit modes.");44 45 PTXVersion = 32;46 for (const StringRef Feature : Opts.FeaturesAsWritten) {47 int PTXV;48 if (!Feature.starts_with("+ptx") ||49 Feature.drop_front(4).getAsInteger(10, PTXV))50 continue;51 PTXVersion = PTXV; // TODO: should it be max(PTXVersion, PTXV)?52 }53 54 TLSSupported = false;55 VLASupported = false;56 AddrSpaceMap = &NVPTXAddrSpaceMap;57 UseAddrSpaceMapMangling = true;58 // __bf16 is always available as a load/store only type.59 BFloat16Width = BFloat16Align = 16;60 BFloat16Format = &llvm::APFloat::BFloat();61 62 // Define available target features63 // These must be defined in sorted order!64 NoAsmVariants = true;65 GPU = OffloadArch::UNUSED;66 67 // PTX supports f16 as a fundamental type.68 HasFastHalfType = true;69 HasFloat16 = true;70 71 if (TargetPointerWidth == 32)72 resetDataLayout("e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:"73 "16-v32:32-n16:32:64");74 else if (Opts.NVPTXUseShortPointers)75 resetDataLayout("e-p3:32:32-p4:32:32-p5:32:32-p6:32:32-p7:32:32-i64:64-"76 "i128:128-i256:256-v16:"77 "16-v32:32-n16:32:64");78 else79 resetDataLayout(80 "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64");81 82 // If possible, get a TargetInfo for our host triple, so we can match its83 // types.84 llvm::Triple HostTriple(Opts.HostTriple);85 if (!HostTriple.isNVPTX())86 HostTarget = AllocateTarget(llvm::Triple(Opts.HostTriple), Opts);87 88 // If no host target, make some guesses about the data layout and return.89 if (!HostTarget) {90 LongWidth = LongAlign = TargetPointerWidth;91 PointerWidth = PointerAlign = TargetPointerWidth;92 switch (TargetPointerWidth) {93 case 32:94 SizeType = TargetInfo::UnsignedInt;95 PtrDiffType = TargetInfo::SignedInt;96 IntPtrType = TargetInfo::SignedInt;97 break;98 case 64:99 SizeType = TargetInfo::UnsignedLong;100 PtrDiffType = TargetInfo::SignedLong;101 IntPtrType = TargetInfo::SignedLong;102 break;103 default:104 llvm_unreachable("TargetPointerWidth must be 32 or 64");105 }106 107 MaxAtomicInlineWidth = TargetPointerWidth;108 return;109 }110 111 // Copy properties from host target.112 PointerWidth = HostTarget->getPointerWidth(LangAS::Default);113 PointerAlign = HostTarget->getPointerAlign(LangAS::Default);114 BoolWidth = HostTarget->getBoolWidth();115 BoolAlign = HostTarget->getBoolAlign();116 IntWidth = HostTarget->getIntWidth();117 IntAlign = HostTarget->getIntAlign();118 HalfWidth = HostTarget->getHalfWidth();119 HalfAlign = HostTarget->getHalfAlign();120 FloatWidth = HostTarget->getFloatWidth();121 FloatAlign = HostTarget->getFloatAlign();122 DoubleWidth = HostTarget->getDoubleWidth();123 DoubleAlign = HostTarget->getDoubleAlign();124 LongWidth = HostTarget->getLongWidth();125 LongAlign = HostTarget->getLongAlign();126 LongLongWidth = HostTarget->getLongLongWidth();127 LongLongAlign = HostTarget->getLongLongAlign();128 MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0,129 /* HasNonWeakDef = */ true);130 NewAlign = HostTarget->getNewAlign();131 DefaultAlignForAttributeAligned =132 HostTarget->getDefaultAlignForAttributeAligned();133 SizeType = HostTarget->getSizeType();134 IntMaxType = HostTarget->getIntMaxType();135 PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default);136 IntPtrType = HostTarget->getIntPtrType();137 WCharType = HostTarget->getWCharType();138 WIntType = HostTarget->getWIntType();139 Char16Type = HostTarget->getChar16Type();140 Char32Type = HostTarget->getChar32Type();141 Int64Type = HostTarget->getInt64Type();142 SigAtomicType = HostTarget->getSigAtomicType();143 ProcessIDType = HostTarget->getProcessIDType();144 145 UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();146 UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();147 UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();148 ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();149 150 // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and151 // we need those macros to be identical on host and device, because (among152 // other things) they affect which standard library classes are defined, and153 // we need all classes to be defined on both the host and device.154 MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();155 156 // Properties intentionally not copied from host:157 // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the158 // host/device boundary.159 // - SuitableAlign: Not visible across the host/device boundary, and may160 // correctly be different on host/device, e.g. if host has wider vector161 // types than device.162 // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same163 // as its double type, but that's not necessarily true on the host.164 // TODO: nvcc emits a warning when using long double on device; we should165 // do the same.166}167 168ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {169 return llvm::ArrayRef(GCCRegNames);170}171 172bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {173 return llvm::StringSwitch<bool>(Feature)174 .Cases({"ptx", "nvptx"}, true)175 .Default(false);176}177 178void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,179 MacroBuilder &Builder) const {180 Builder.defineMacro("__PTX__");181 Builder.defineMacro("__NVPTX__");182 183 // Skip setting architecture dependent macros if undefined.184 if (GPU == OffloadArch::UNUSED && !HostTarget)185 return;186 187 if (Opts.CUDAIsDevice || Opts.OpenMPIsTargetDevice || !HostTarget) {188 // Set __CUDA_ARCH__ for the GPU specified.189 llvm::StringRef CUDAArchCode = [this] {190 switch (GPU) {191 case OffloadArch::GFX600:192 case OffloadArch::GFX601:193 case OffloadArch::GFX602:194 case OffloadArch::GFX700:195 case OffloadArch::GFX701:196 case OffloadArch::GFX702:197 case OffloadArch::GFX703:198 case OffloadArch::GFX704:199 case OffloadArch::GFX705:200 case OffloadArch::GFX801:201 case OffloadArch::GFX802:202 case OffloadArch::GFX803:203 case OffloadArch::GFX805:204 case OffloadArch::GFX810:205 case OffloadArch::GFX9_GENERIC:206 case OffloadArch::GFX900:207 case OffloadArch::GFX902:208 case OffloadArch::GFX904:209 case OffloadArch::GFX906:210 case OffloadArch::GFX908:211 case OffloadArch::GFX909:212 case OffloadArch::GFX90a:213 case OffloadArch::GFX90c:214 case OffloadArch::GFX9_4_GENERIC:215 case OffloadArch::GFX942:216 case OffloadArch::GFX950:217 case OffloadArch::GFX10_1_GENERIC:218 case OffloadArch::GFX1010:219 case OffloadArch::GFX1011:220 case OffloadArch::GFX1012:221 case OffloadArch::GFX1013:222 case OffloadArch::GFX10_3_GENERIC:223 case OffloadArch::GFX1030:224 case OffloadArch::GFX1031:225 case OffloadArch::GFX1032:226 case OffloadArch::GFX1033:227 case OffloadArch::GFX1034:228 case OffloadArch::GFX1035:229 case OffloadArch::GFX1036:230 case OffloadArch::GFX11_GENERIC:231 case OffloadArch::GFX1100:232 case OffloadArch::GFX1101:233 case OffloadArch::GFX1102:234 case OffloadArch::GFX1103:235 case OffloadArch::GFX1150:236 case OffloadArch::GFX1151:237 case OffloadArch::GFX1152:238 case OffloadArch::GFX1153:239 case OffloadArch::GFX12_GENERIC:240 case OffloadArch::GFX1200:241 case OffloadArch::GFX1201:242 case OffloadArch::GFX1250:243 case OffloadArch::GFX1251:244 case OffloadArch::AMDGCNSPIRV:245 case OffloadArch::Generic:246 case OffloadArch::GRANITERAPIDS:247 case OffloadArch::BMG_G21:248 case OffloadArch::LAST:249 break;250 case OffloadArch::UNKNOWN:251 assert(false && "No GPU arch when compiling CUDA device code.");252 return "";253 case OffloadArch::UNUSED:254 case OffloadArch::SM_20:255 return "200";256 case OffloadArch::SM_21:257 return "210";258 case OffloadArch::SM_30:259 return "300";260 case OffloadArch::SM_32_:261 return "320";262 case OffloadArch::SM_35:263 return "350";264 case OffloadArch::SM_37:265 return "370";266 case OffloadArch::SM_50:267 return "500";268 case OffloadArch::SM_52:269 return "520";270 case OffloadArch::SM_53:271 return "530";272 case OffloadArch::SM_60:273 return "600";274 case OffloadArch::SM_61:275 return "610";276 case OffloadArch::SM_62:277 return "620";278 case OffloadArch::SM_70:279 return "700";280 case OffloadArch::SM_72:281 return "720";282 case OffloadArch::SM_75:283 return "750";284 case OffloadArch::SM_80:285 return "800";286 case OffloadArch::SM_86:287 return "860";288 case OffloadArch::SM_87:289 return "870";290 case OffloadArch::SM_89:291 return "890";292 case OffloadArch::SM_90:293 case OffloadArch::SM_90a:294 return "900";295 case OffloadArch::SM_100:296 case OffloadArch::SM_100a:297 return "1000";298 case OffloadArch::SM_101:299 case OffloadArch::SM_101a:300 return "1010";301 case OffloadArch::SM_103:302 case OffloadArch::SM_103a:303 return "1030";304 case OffloadArch::SM_120:305 case OffloadArch::SM_120a:306 return "1200";307 case OffloadArch::SM_121:308 case OffloadArch::SM_121a:309 return "1210";310 }311 llvm_unreachable("unhandled OffloadArch");312 }();313 Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);314 switch(GPU) {315 case OffloadArch::SM_90a:316 case OffloadArch::SM_100a:317 case OffloadArch::SM_101a:318 case OffloadArch::SM_103a:319 case OffloadArch::SM_120a:320 case OffloadArch::SM_121a:321 Builder.defineMacro("__CUDA_ARCH_FEAT_SM" + CUDAArchCode.drop_back() + "_ALL", "1");322 break;323 default:324 // Do nothing if this is not an enhanced architecture.325 break;326 }327 }328}329 330llvm::SmallVector<Builtin::InfosShard>331NVPTXTargetInfo::getTargetBuiltins() const {332 return {{&BuiltinStrings, BuiltinInfos}};333}334