xref: /llvm-project/clang/lib/CodeGen/Targets/NVPTX.cpp (revision 4583f6d3443c8dc6605c868724e3743161954210)
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