1992cb984SSergei Barannikov //===- NVPTX.cpp ----------------------------------------------------------===// 2992cb984SSergei Barannikov // 3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information. 5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6992cb984SSergei Barannikov // 7992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 8992cb984SSergei Barannikov 9992cb984SSergei Barannikov #include "ABIInfoImpl.h" 10992cb984SSergei Barannikov #include "TargetInfo.h" 117c3fdcc2SArtem Belevich #include "llvm/ADT/STLExtras.h" 12*4583f6d3SAlex MacLean #include "llvm/IR/CallingConv.h" 13992cb984SSergei Barannikov #include "llvm/IR/IntrinsicsNVPTX.h" 14992cb984SSergei Barannikov 15992cb984SSergei Barannikov using namespace clang; 16992cb984SSergei Barannikov using namespace clang::CodeGen; 17992cb984SSergei Barannikov 18992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 19992cb984SSergei Barannikov // NVPTX ABI Implementation 20992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 21992cb984SSergei Barannikov 22992cb984SSergei Barannikov namespace { 23992cb984SSergei Barannikov 24992cb984SSergei Barannikov class NVPTXTargetCodeGenInfo; 25992cb984SSergei Barannikov 26992cb984SSergei Barannikov class NVPTXABIInfo : public ABIInfo { 27992cb984SSergei Barannikov NVPTXTargetCodeGenInfo &CGInfo; 28992cb984SSergei Barannikov 29992cb984SSergei Barannikov public: 30992cb984SSergei Barannikov NVPTXABIInfo(CodeGenTypes &CGT, NVPTXTargetCodeGenInfo &Info) 31992cb984SSergei Barannikov : ABIInfo(CGT), CGInfo(Info) {} 32992cb984SSergei Barannikov 33992cb984SSergei Barannikov ABIArgInfo classifyReturnType(QualType RetTy) const; 34992cb984SSergei Barannikov ABIArgInfo classifyArgumentType(QualType Ty) const; 35992cb984SSergei Barannikov 36992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override; 376d973b45SMariya Podchishchaeva RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 386d973b45SMariya Podchishchaeva AggValueSlot Slot) const override; 39992cb984SSergei Barannikov bool isUnsupportedType(QualType T) const; 40992cb984SSergei Barannikov ABIArgInfo coerceToIntArrayWithLimit(QualType Ty, unsigned MaxSize) const; 41992cb984SSergei Barannikov }; 42992cb984SSergei Barannikov 43992cb984SSergei Barannikov class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo { 44992cb984SSergei Barannikov public: 45992cb984SSergei Barannikov NVPTXTargetCodeGenInfo(CodeGenTypes &CGT) 46992cb984SSergei Barannikov : TargetCodeGenInfo(std::make_unique<NVPTXABIInfo>(CGT, *this)) {} 47992cb984SSergei Barannikov 48992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 49992cb984SSergei Barannikov CodeGen::CodeGenModule &M) const override; 50992cb984SSergei Barannikov bool shouldEmitStaticExternCAliases() const override; 51992cb984SSergei Barannikov 52f5400447Smmoadeli llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, 53f5400447Smmoadeli llvm::PointerType *T, 54f5400447Smmoadeli QualType QT) const override; 55f5400447Smmoadeli 56992cb984SSergei Barannikov llvm::Type *getCUDADeviceBuiltinSurfaceDeviceType() const override { 57992cb984SSergei Barannikov // On the device side, surface reference is represented as an object handle 58992cb984SSergei Barannikov // in 64-bit integer. 59992cb984SSergei Barannikov return llvm::Type::getInt64Ty(getABIInfo().getVMContext()); 60992cb984SSergei Barannikov } 61992cb984SSergei Barannikov 62992cb984SSergei Barannikov llvm::Type *getCUDADeviceBuiltinTextureDeviceType() const override { 63992cb984SSergei Barannikov // On the device side, texture reference is represented as an object handle 64992cb984SSergei Barannikov // in 64-bit integer. 65992cb984SSergei Barannikov return llvm::Type::getInt64Ty(getABIInfo().getVMContext()); 66992cb984SSergei Barannikov } 67992cb984SSergei Barannikov 68992cb984SSergei Barannikov bool emitCUDADeviceBuiltinSurfaceDeviceCopy(CodeGenFunction &CGF, LValue Dst, 69992cb984SSergei Barannikov LValue Src) const override { 70992cb984SSergei Barannikov emitBuiltinSurfTexDeviceCopy(CGF, Dst, Src); 71992cb984SSergei Barannikov return true; 72992cb984SSergei Barannikov } 73992cb984SSergei Barannikov 74992cb984SSergei Barannikov bool emitCUDADeviceBuiltinTextureDeviceCopy(CodeGenFunction &CGF, LValue Dst, 75992cb984SSergei Barannikov LValue Src) const override { 76992cb984SSergei Barannikov emitBuiltinSurfTexDeviceCopy(CGF, Dst, Src); 77992cb984SSergei Barannikov return true; 78992cb984SSergei Barannikov } 79992cb984SSergei Barannikov 80992cb984SSergei Barannikov // Adds a NamedMDNode with GV, Name, and Operand as operands, and adds the 81992cb984SSergei Barannikov // resulting MDNode to the nvvm.annotations MDNode. 82992cb984SSergei Barannikov static void addNVVMMetadata(llvm::GlobalValue *GV, StringRef Name, 83*4583f6d3SAlex MacLean int Operand); 847c3fdcc2SArtem Belevich 85*4583f6d3SAlex MacLean static void 86*4583f6d3SAlex MacLean addGridConstantNVVMMetadata(llvm::GlobalValue *GV, 87*4583f6d3SAlex MacLean const SmallVectorImpl<int> &GridConstantArgs); 88992cb984SSergei Barannikov 8908a22076SJohannes Doerfert private: 90992cb984SSergei Barannikov static void emitBuiltinSurfTexDeviceCopy(CodeGenFunction &CGF, LValue Dst, 91992cb984SSergei Barannikov LValue Src) { 92992cb984SSergei Barannikov llvm::Value *Handle = nullptr; 93992cb984SSergei Barannikov llvm::Constant *C = 943575d23cSAhmed Bougacha llvm::dyn_cast<llvm::Constant>(Src.getAddress().emitRawPointer(CGF)); 95992cb984SSergei Barannikov // Lookup `addrspacecast` through the constant pointer if any. 96992cb984SSergei Barannikov if (auto *ASC = llvm::dyn_cast_or_null<llvm::AddrSpaceCastOperator>(C)) 97992cb984SSergei Barannikov C = llvm::cast<llvm::Constant>(ASC->getPointerOperand()); 98992cb984SSergei Barannikov if (auto *GV = llvm::dyn_cast_or_null<llvm::GlobalVariable>(C)) { 99992cb984SSergei Barannikov // Load the handle from the specific global variable using 100992cb984SSergei Barannikov // `nvvm.texsurf.handle.internal` intrinsic. 101992cb984SSergei Barannikov Handle = CGF.EmitRuntimeCall( 102992cb984SSergei Barannikov CGF.CGM.getIntrinsic(llvm::Intrinsic::nvvm_texsurf_handle_internal, 103992cb984SSergei Barannikov {GV->getType()}), 104992cb984SSergei Barannikov {GV}, "texsurf_handle"); 105992cb984SSergei Barannikov } else 106992cb984SSergei Barannikov Handle = CGF.EmitLoadOfScalar(Src, SourceLocation()); 107992cb984SSergei Barannikov CGF.EmitStoreOfScalar(Handle, Dst); 108992cb984SSergei Barannikov } 109992cb984SSergei Barannikov }; 110992cb984SSergei Barannikov 111992cb984SSergei Barannikov /// Checks if the type is unsupported directly by the current target. 112992cb984SSergei Barannikov bool NVPTXABIInfo::isUnsupportedType(QualType T) const { 113992cb984SSergei Barannikov ASTContext &Context = getContext(); 114992cb984SSergei Barannikov if (!Context.getTargetInfo().hasFloat16Type() && T->isFloat16Type()) 115992cb984SSergei Barannikov return true; 116992cb984SSergei Barannikov if (!Context.getTargetInfo().hasFloat128Type() && 117992cb984SSergei Barannikov (T->isFloat128Type() || 118992cb984SSergei Barannikov (T->isRealFloatingType() && Context.getTypeSize(T) == 128))) 119992cb984SSergei Barannikov return true; 120992cb984SSergei Barannikov if (const auto *EIT = T->getAs<BitIntType>()) 121992cb984SSergei Barannikov return EIT->getNumBits() > 122992cb984SSergei Barannikov (Context.getTargetInfo().hasInt128Type() ? 128U : 64U); 123992cb984SSergei Barannikov if (!Context.getTargetInfo().hasInt128Type() && T->isIntegerType() && 124992cb984SSergei Barannikov Context.getTypeSize(T) > 64U) 125992cb984SSergei Barannikov return true; 126992cb984SSergei Barannikov if (const auto *AT = T->getAsArrayTypeUnsafe()) 127992cb984SSergei Barannikov return isUnsupportedType(AT->getElementType()); 128992cb984SSergei Barannikov const auto *RT = T->getAs<RecordType>(); 129992cb984SSergei Barannikov if (!RT) 130992cb984SSergei Barannikov return false; 131992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 132992cb984SSergei Barannikov 133992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 134992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 135992cb984SSergei Barannikov for (const CXXBaseSpecifier &I : CXXRD->bases()) 136992cb984SSergei Barannikov if (isUnsupportedType(I.getType())) 137992cb984SSergei Barannikov return true; 138992cb984SSergei Barannikov 139992cb984SSergei Barannikov for (const FieldDecl *I : RD->fields()) 140992cb984SSergei Barannikov if (isUnsupportedType(I->getType())) 141992cb984SSergei Barannikov return true; 142992cb984SSergei Barannikov return false; 143992cb984SSergei Barannikov } 144992cb984SSergei Barannikov 145992cb984SSergei Barannikov /// Coerce the given type into an array with maximum allowed size of elements. 146992cb984SSergei Barannikov ABIArgInfo NVPTXABIInfo::coerceToIntArrayWithLimit(QualType Ty, 147992cb984SSergei Barannikov unsigned MaxSize) const { 148992cb984SSergei Barannikov // Alignment and Size are measured in bits. 149992cb984SSergei Barannikov const uint64_t Size = getContext().getTypeSize(Ty); 150992cb984SSergei Barannikov const uint64_t Alignment = getContext().getTypeAlign(Ty); 151992cb984SSergei Barannikov const unsigned Div = std::min<unsigned>(MaxSize, Alignment); 152992cb984SSergei Barannikov llvm::Type *IntType = llvm::Type::getIntNTy(getVMContext(), Div); 153992cb984SSergei Barannikov const uint64_t NumElements = (Size + Div - 1) / Div; 154992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements)); 155992cb984SSergei Barannikov } 156992cb984SSergei Barannikov 157992cb984SSergei Barannikov ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const { 158992cb984SSergei Barannikov if (RetTy->isVoidType()) 159992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 160992cb984SSergei Barannikov 161992cb984SSergei Barannikov if (getContext().getLangOpts().OpenMP && 16263ca93c7SSergio Afonso getContext().getLangOpts().OpenMPIsTargetDevice && 16363ca93c7SSergio Afonso isUnsupportedType(RetTy)) 164992cb984SSergei Barannikov return coerceToIntArrayWithLimit(RetTy, 64); 165992cb984SSergei Barannikov 166992cb984SSergei Barannikov // note: this is different from default ABI 167992cb984SSergei Barannikov if (!RetTy->isScalarType()) 168992cb984SSergei Barannikov return ABIArgInfo::getDirect(); 169992cb984SSergei Barannikov 170992cb984SSergei Barannikov // Treat an enum type as its underlying type. 171992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 172992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType(); 173992cb984SSergei Barannikov 174992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 175992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 176992cb984SSergei Barannikov } 177992cb984SSergei Barannikov 178992cb984SSergei Barannikov ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { 179992cb984SSergei Barannikov // Treat an enum type as its underlying type. 180992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 181992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 182992cb984SSergei Barannikov 183992cb984SSergei Barannikov // Return aggregates type as indirect by value 184992cb984SSergei Barannikov if (isAggregateTypeForABI(Ty)) { 185992cb984SSergei Barannikov // Under CUDA device compilation, tex/surf builtin types are replaced with 186992cb984SSergei Barannikov // object types and passed directly. 187992cb984SSergei Barannikov if (getContext().getLangOpts().CUDAIsDevice) { 188992cb984SSergei Barannikov if (Ty->isCUDADeviceBuiltinSurfaceType()) 189992cb984SSergei Barannikov return ABIArgInfo::getDirect( 190992cb984SSergei Barannikov CGInfo.getCUDADeviceBuiltinSurfaceDeviceType()); 191992cb984SSergei Barannikov if (Ty->isCUDADeviceBuiltinTextureType()) 192992cb984SSergei Barannikov return ABIArgInfo::getDirect( 193992cb984SSergei Barannikov CGInfo.getCUDADeviceBuiltinTextureDeviceType()); 194992cb984SSergei Barannikov } 195992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /* byval */ true); 196992cb984SSergei Barannikov } 197992cb984SSergei Barannikov 198992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) { 199992cb984SSergei Barannikov if ((EIT->getNumBits() > 128) || 200992cb984SSergei Barannikov (!getContext().getTargetInfo().hasInt128Type() && 201992cb984SSergei Barannikov EIT->getNumBits() > 64)) 202992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /* byval */ true); 203992cb984SSergei Barannikov } 204992cb984SSergei Barannikov 205992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 206992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 207992cb984SSergei Barannikov } 208992cb984SSergei Barannikov 209992cb984SSergei Barannikov void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const { 210992cb984SSergei Barannikov if (!getCXXABI().classifyReturnType(FI)) 211992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 212486d00ecSJoseph Huber 213486d00ecSJoseph Huber for (auto &&[ArgumentsCount, I] : llvm::enumerate(FI.arguments())) 214486d00ecSJoseph Huber I.info = ArgumentsCount < FI.getNumRequiredArgs() 215486d00ecSJoseph Huber ? classifyArgumentType(I.type) 216486d00ecSJoseph Huber : ABIArgInfo::getDirect(); 217992cb984SSergei Barannikov 218992cb984SSergei Barannikov // Always honor user-specified calling convention. 219992cb984SSergei Barannikov if (FI.getCallingConvention() != llvm::CallingConv::C) 220992cb984SSergei Barannikov return; 221992cb984SSergei Barannikov 222992cb984SSergei Barannikov FI.setEffectiveCallingConvention(getRuntimeCC()); 223992cb984SSergei Barannikov } 224992cb984SSergei Barannikov 2256d973b45SMariya Podchishchaeva RValue NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 2266d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const { 227486d00ecSJoseph Huber return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/false, 228486d00ecSJoseph Huber getContext().getTypeInfoInChars(Ty), 229486d00ecSJoseph Huber CharUnits::fromQuantity(1), 230486d00ecSJoseph Huber /*AllowHigherAlign=*/true, Slot); 231992cb984SSergei Barannikov } 232992cb984SSergei Barannikov 233992cb984SSergei Barannikov void NVPTXTargetCodeGenInfo::setTargetAttributes( 234992cb984SSergei Barannikov const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { 235992cb984SSergei Barannikov if (GV->isDeclaration()) 236992cb984SSergei Barannikov return; 237992cb984SSergei Barannikov const VarDecl *VD = dyn_cast_or_null<VarDecl>(D); 238992cb984SSergei Barannikov if (VD) { 239992cb984SSergei Barannikov if (M.getLangOpts().CUDA) { 240992cb984SSergei Barannikov if (VD->getType()->isCUDADeviceBuiltinSurfaceType()) 241992cb984SSergei Barannikov addNVVMMetadata(GV, "surface", 1); 242992cb984SSergei Barannikov else if (VD->getType()->isCUDADeviceBuiltinTextureType()) 243992cb984SSergei Barannikov addNVVMMetadata(GV, "texture", 1); 244992cb984SSergei Barannikov return; 245992cb984SSergei Barannikov } 246992cb984SSergei Barannikov } 247992cb984SSergei Barannikov 248992cb984SSergei Barannikov const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 2497c3fdcc2SArtem Belevich if (!FD) 2507c3fdcc2SArtem Belevich return; 251992cb984SSergei Barannikov 252992cb984SSergei Barannikov llvm::Function *F = cast<llvm::Function>(GV); 253992cb984SSergei Barannikov 254992cb984SSergei Barannikov // Perform special handling in OpenCL mode 255992cb984SSergei Barannikov if (M.getLangOpts().OpenCL) { 256992cb984SSergei Barannikov // Use OpenCL function attributes to check for kernel functions 257992cb984SSergei Barannikov // By default, all functions are device functions 258992cb984SSergei Barannikov if (FD->hasAttr<OpenCLKernelAttr>()) { 259992cb984SSergei Barannikov // OpenCL __kernel functions get kernel metadata 260992cb984SSergei Barannikov // Create !{<func-ref>, metadata !"kernel", i32 1} node 261*4583f6d3SAlex MacLean F->setCallingConv(llvm::CallingConv::PTX_Kernel); 262992cb984SSergei Barannikov // And kernel functions are not subject to inlining 263992cb984SSergei Barannikov F->addFnAttr(llvm::Attribute::NoInline); 264992cb984SSergei Barannikov } 265992cb984SSergei Barannikov } 266992cb984SSergei Barannikov 267992cb984SSergei Barannikov // Perform special handling in CUDA mode. 268992cb984SSergei Barannikov if (M.getLangOpts().CUDA) { 269992cb984SSergei Barannikov // CUDA __global__ functions get a kernel metadata entry. Since 270992cb984SSergei Barannikov // __global__ functions cannot be called from the device, we do not 271992cb984SSergei Barannikov // need to set the noinline attribute. 272992cb984SSergei Barannikov if (FD->hasAttr<CUDAGlobalAttr>()) { 2737c3fdcc2SArtem Belevich SmallVector<int, 10> GCI; 2747c3fdcc2SArtem Belevich for (auto IV : llvm::enumerate(FD->parameters())) 2757c3fdcc2SArtem Belevich if (IV.value()->hasAttr<CUDAGridConstantAttr>()) 2767c3fdcc2SArtem Belevich // For some reason arg indices are 1-based in NVVM 2777c3fdcc2SArtem Belevich GCI.push_back(IV.index() + 1); 278992cb984SSergei Barannikov // Create !{<func-ref>, metadata !"kernel", i32 1} node 279*4583f6d3SAlex MacLean F->setCallingConv(llvm::CallingConv::PTX_Kernel); 280*4583f6d3SAlex MacLean addGridConstantNVVMMetadata(F, GCI); 281992cb984SSergei Barannikov } 28208a22076SJohannes Doerfert if (CUDALaunchBoundsAttr *Attr = FD->getAttr<CUDALaunchBoundsAttr>()) 28308a22076SJohannes Doerfert M.handleCUDALaunchBoundsAttr(F, Attr); 284992cb984SSergei Barannikov } 285992cb984SSergei Barannikov 286992cb984SSergei Barannikov // Attach kernel metadata directly if compiling for NVPTX. 287992cb984SSergei Barannikov if (FD->hasAttr<NVPTXKernelAttr>()) { 288*4583f6d3SAlex MacLean F->setCallingConv(llvm::CallingConv::PTX_Kernel); 289992cb984SSergei Barannikov } 290992cb984SSergei Barannikov } 291992cb984SSergei Barannikov 292*4583f6d3SAlex MacLean void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::GlobalValue *GV, 293*4583f6d3SAlex MacLean StringRef Name, int Operand) { 294992cb984SSergei Barannikov llvm::Module *M = GV->getParent(); 295992cb984SSergei Barannikov llvm::LLVMContext &Ctx = M->getContext(); 296992cb984SSergei Barannikov 297992cb984SSergei Barannikov // Get "nvvm.annotations" metadata node 298992cb984SSergei Barannikov llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations"); 299992cb984SSergei Barannikov 3007c3fdcc2SArtem Belevich SmallVector<llvm::Metadata *, 5> MDVals = { 301992cb984SSergei Barannikov llvm::ConstantAsMetadata::get(GV), llvm::MDString::get(Ctx, Name), 302992cb984SSergei Barannikov llvm::ConstantAsMetadata::get( 303992cb984SSergei Barannikov llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), Operand))}; 304*4583f6d3SAlex MacLean 305*4583f6d3SAlex MacLean // Append metadata to nvvm.annotations 306*4583f6d3SAlex MacLean MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 307*4583f6d3SAlex MacLean } 308*4583f6d3SAlex MacLean 309*4583f6d3SAlex MacLean void NVPTXTargetCodeGenInfo::addGridConstantNVVMMetadata( 310*4583f6d3SAlex MacLean llvm::GlobalValue *GV, const SmallVectorImpl<int> &GridConstantArgs) { 311*4583f6d3SAlex MacLean 312*4583f6d3SAlex MacLean llvm::Module *M = GV->getParent(); 313*4583f6d3SAlex MacLean llvm::LLVMContext &Ctx = M->getContext(); 314*4583f6d3SAlex MacLean 315*4583f6d3SAlex MacLean // Get "nvvm.annotations" metadata node 316*4583f6d3SAlex MacLean llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations"); 317*4583f6d3SAlex MacLean 318*4583f6d3SAlex MacLean SmallVector<llvm::Metadata *, 5> MDVals = {llvm::ConstantAsMetadata::get(GV)}; 3197c3fdcc2SArtem Belevich if (!GridConstantArgs.empty()) { 3207c3fdcc2SArtem Belevich SmallVector<llvm::Metadata *, 10> GCM; 3217c3fdcc2SArtem Belevich for (int I : GridConstantArgs) 3227c3fdcc2SArtem Belevich GCM.push_back(llvm::ConstantAsMetadata::get( 3237c3fdcc2SArtem Belevich llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), I))); 3247c3fdcc2SArtem Belevich MDVals.append({llvm::MDString::get(Ctx, "grid_constant"), 3257c3fdcc2SArtem Belevich llvm::MDNode::get(Ctx, GCM)}); 3267c3fdcc2SArtem Belevich } 327*4583f6d3SAlex MacLean 328992cb984SSergei Barannikov // Append metadata to nvvm.annotations 329992cb984SSergei Barannikov MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 330992cb984SSergei Barannikov } 331992cb984SSergei Barannikov 332992cb984SSergei Barannikov bool NVPTXTargetCodeGenInfo::shouldEmitStaticExternCAliases() const { 333992cb984SSergei Barannikov return false; 334992cb984SSergei Barannikov } 335f5400447Smmoadeli 336f5400447Smmoadeli llvm::Constant * 337f5400447Smmoadeli NVPTXTargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, 338f5400447Smmoadeli llvm::PointerType *PT, 339f5400447Smmoadeli QualType QT) const { 340f5400447Smmoadeli auto &Ctx = CGM.getContext(); 341f5400447Smmoadeli if (PT->getAddressSpace() != Ctx.getTargetAddressSpace(LangAS::opencl_local)) 342f5400447Smmoadeli return llvm::ConstantPointerNull::get(PT); 343f5400447Smmoadeli 344f5400447Smmoadeli auto NPT = llvm::PointerType::get( 345f5400447Smmoadeli PT->getContext(), Ctx.getTargetAddressSpace(LangAS::opencl_generic)); 346f5400447Smmoadeli return llvm::ConstantExpr::getAddrSpaceCast( 347f5400447Smmoadeli llvm::ConstantPointerNull::get(NPT), PT); 348f5400447Smmoadeli } 3497c3fdcc2SArtem Belevich } // namespace 350992cb984SSergei Barannikov 3510ba57c8bSJohannes Doerfert void CodeGenModule::handleCUDALaunchBoundsAttr(llvm::Function *F, 3520ba57c8bSJohannes Doerfert const CUDALaunchBoundsAttr *Attr, 3530ba57c8bSJohannes Doerfert int32_t *MaxThreadsVal, 3540ba57c8bSJohannes Doerfert int32_t *MinBlocksVal, 3550ba57c8bSJohannes Doerfert int32_t *MaxClusterRankVal) { 35608a22076SJohannes Doerfert // Create !{<func-ref>, metadata !"maxntidx", i32 <val>} node 35708a22076SJohannes Doerfert llvm::APSInt MaxThreads(32); 35808a22076SJohannes Doerfert MaxThreads = Attr->getMaxThreads()->EvaluateKnownConstInt(getContext()); 3590ba57c8bSJohannes Doerfert if (MaxThreads > 0) { 3600ba57c8bSJohannes Doerfert if (MaxThreadsVal) 3610ba57c8bSJohannes Doerfert *MaxThreadsVal = MaxThreads.getExtValue(); 3620ba57c8bSJohannes Doerfert if (F) { 3630ba57c8bSJohannes Doerfert // Create !{<func-ref>, metadata !"maxntidx", i32 <val>} node 36408a22076SJohannes Doerfert NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "maxntidx", 36508a22076SJohannes Doerfert MaxThreads.getExtValue()); 3660ba57c8bSJohannes Doerfert } 3670ba57c8bSJohannes Doerfert } 36808a22076SJohannes Doerfert 3693f8d4a8eSJakub Chlanda // min and max blocks is an optional argument for CUDALaunchBoundsAttr. If it 3703f8d4a8eSJakub Chlanda // was not specified in __launch_bounds__ or if the user specified a 0 value, 37108a22076SJohannes Doerfert // we don't have to add a PTX directive. 37208a22076SJohannes Doerfert if (Attr->getMinBlocks()) { 37308a22076SJohannes Doerfert llvm::APSInt MinBlocks(32); 37408a22076SJohannes Doerfert MinBlocks = Attr->getMinBlocks()->EvaluateKnownConstInt(getContext()); 3750ba57c8bSJohannes Doerfert if (MinBlocks > 0) { 3760ba57c8bSJohannes Doerfert if (MinBlocksVal) 3770ba57c8bSJohannes Doerfert *MinBlocksVal = MinBlocks.getExtValue(); 3780ba57c8bSJohannes Doerfert if (F) { 37908a22076SJohannes Doerfert // Create !{<func-ref>, metadata !"minctasm", i32 <val>} node 38008a22076SJohannes Doerfert NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "minctasm", 38108a22076SJohannes Doerfert MinBlocks.getExtValue()); 38208a22076SJohannes Doerfert } 3830ba57c8bSJohannes Doerfert } 3840ba57c8bSJohannes Doerfert } 3853f8d4a8eSJakub Chlanda if (Attr->getMaxBlocks()) { 3863f8d4a8eSJakub Chlanda llvm::APSInt MaxBlocks(32); 3873f8d4a8eSJakub Chlanda MaxBlocks = Attr->getMaxBlocks()->EvaluateKnownConstInt(getContext()); 3880ba57c8bSJohannes Doerfert if (MaxBlocks > 0) { 3890ba57c8bSJohannes Doerfert if (MaxClusterRankVal) 3900ba57c8bSJohannes Doerfert *MaxClusterRankVal = MaxBlocks.getExtValue(); 3910ba57c8bSJohannes Doerfert if (F) { 3923f8d4a8eSJakub Chlanda // Create !{<func-ref>, metadata !"maxclusterrank", i32 <val>} node 3933f8d4a8eSJakub Chlanda NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "maxclusterrank", 3943f8d4a8eSJakub Chlanda MaxBlocks.getExtValue()); 3953f8d4a8eSJakub Chlanda } 39608a22076SJohannes Doerfert } 3970ba57c8bSJohannes Doerfert } 3980ba57c8bSJohannes Doerfert } 39908a22076SJohannes Doerfert 400992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 401992cb984SSergei Barannikov CodeGen::createNVPTXTargetCodeGenInfo(CodeGenModule &CGM) { 402992cb984SSergei Barannikov return std::make_unique<NVPTXTargetCodeGenInfo>(CGM.getTypes()); 403992cb984SSergei Barannikov } 404