10#include "TargetInfo.h"
12#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringExtras.h"
14#include "llvm/IR/CallingConv.h"
15#include "llvm/IR/IntrinsicsNVPTX.h"
16#include "llvm/IR/LLVMContext.h"
17#include "llvm/Support/NVVMAttributes.h"
28class NVPTXTargetCodeGenInfo;
30class NVPTXABIInfo :
public ABIInfo {
31 NVPTXTargetCodeGenInfo &CGInfo;
34 NVPTXABIInfo(CodeGenTypes &CGT, NVPTXTargetCodeGenInfo &Info)
35 : ABIInfo(CGT), CGInfo(Info) {}
40 void computeInfo(CGFunctionInfo &FI)
const override;
41 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
42 AggValueSlot Slot)
const override;
43 bool isUnsupportedType(QualType
T)
const;
44 ABIArgInfo coerceToIntArrayWithLimit(QualType Ty,
unsigned MaxSize)
const;
49 NVPTXTargetCodeGenInfo(CodeGenTypes &CGT)
50 : TargetCodeGenInfo(std::make_unique<NVPTXABIInfo>(CGT, *this)) {}
52 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
53 CodeGen::CodeGenModule &M)
const override;
54 void setTargetAtomicMetadata(CodeGenFunction &CGF,
55 llvm::Instruction &AtomicInst,
56 const AtomicExpr *AE)
const override;
57 bool shouldEmitStaticExternCAliases()
const override;
59 StringRef getLLVMSyncScopeStr(
const LangOptions &LangOpts,
SyncScope Scope,
60 llvm::AtomicOrdering Ordering)
const override;
62 llvm::Constant *getNullPointer(
const CodeGen::CodeGenModule &CGM,
64 QualType QT)
const override;
66 llvm::Type *getCUDADeviceBuiltinSurfaceDeviceType()
const override {
69 return llvm::Type::getInt64Ty(getABIInfo().getVMContext());
72 llvm::Type *getCUDADeviceBuiltinTextureDeviceType()
const override {
75 return llvm::Type::getInt64Ty(getABIInfo().getVMContext());
78 bool emitCUDADeviceBuiltinSurfaceDeviceCopy(CodeGenFunction &CGF, LValue Dst,
79 LValue Src)
const override {
80 emitBuiltinSurfTexDeviceCopy(CGF, Dst, Src);
84 bool emitCUDADeviceBuiltinTextureDeviceCopy(CodeGenFunction &CGF, LValue Dst,
85 LValue Src)
const override {
86 emitBuiltinSurfTexDeviceCopy(CGF, Dst, Src);
90 unsigned getDeviceKernelCallingConv()
const override {
91 return llvm::CallingConv::PTX_Kernel;
95 FT = getABIInfo().getContext().adjustFunctionType(
101 static void addNVVMMetadata(llvm::GlobalValue *GV, StringRef Name,
105 static void emitBuiltinSurfTexDeviceCopy(CodeGenFunction &CGF, LValue Dst,
107 llvm::Value *Handle =
nullptr;
109 llvm::dyn_cast<llvm::Constant>(Src.getAddress().emitRawPointer(CGF));
111 if (
auto *ASC = llvm::dyn_cast_or_null<llvm::AddrSpaceCastOperator>(
C))
112 C = llvm::cast<llvm::Constant>(ASC->getPointerOperand());
113 if (
auto *GV = llvm::dyn_cast_or_null<llvm::GlobalVariable>(
C)) {
119 {GV},
"texsurf_handle");
127bool NVPTXABIInfo::isUnsupportedType(
QualType T)
const {
128 ASTContext &Context = getContext();
135 if (
const auto *EIT =
T->
getAs<BitIntType>())
136 return EIT->getNumBits() >
142 return isUnsupportedType(AT->getElementType());
148 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
149 for (
const CXXBaseSpecifier &I : CXXRD->bases())
150 if (isUnsupportedType(I.getType()))
153 for (
const FieldDecl *I : RD->fields())
154 if (isUnsupportedType(I->getType()))
160ABIArgInfo NVPTXABIInfo::coerceToIntArrayWithLimit(QualType Ty,
161 unsigned MaxSize)
const {
164 const uint64_t Alignment = getContext().getTypeAlign(Ty);
165 const unsigned Div = std::min<unsigned>(MaxSize, Alignment);
166 llvm::Type *IntType = llvm::Type::getIntNTy(getVMContext(), Div);
171ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy)
const {
175 if (getContext().getLangOpts().OpenMP &&
176 getContext().getLangOpts().OpenMPIsTargetDevice &&
177 isUnsupportedType(RetTy))
178 return coerceToIntArrayWithLimit(RetTy, 64);
186 RetTy = ED->getIntegerType();
192ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty)
const {
195 Ty = ED->getIntegerType();
201 if (getContext().getLangOpts().CUDAIsDevice) {
204 CGInfo.getCUDADeviceBuiltinSurfaceDeviceType());
207 CGInfo.getCUDADeviceBuiltinTextureDeviceType());
209 return getNaturalAlignIndirect(
210 Ty, getDataLayout().getAllocaAddrSpace(),
214 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
215 if ((EIT->getNumBits() > 128) ||
216 (!getContext().getTargetInfo().hasInt128Type() &&
217 EIT->getNumBits() > 64))
218 return getNaturalAlignIndirect(
219 Ty, getDataLayout().getAllocaAddrSpace(),
227void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI)
const {
231 for (
auto &&[ArgumentsCount, I] : llvm::enumerate(FI.
arguments()))
234 : ABIArgInfo::getDirect();
243RValue NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
244 QualType Ty, AggValueSlot Slot)
const {
246 getContext().getTypeInfoInChars(Ty),
251void NVPTXTargetCodeGenInfo::setTargetAttributes(
252 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M)
const {
253 if (GV->isDeclaration())
255 const VarDecl *VD = dyn_cast_or_null<VarDecl>(D);
259 addNVVMMetadata(GV,
"surface", 1);
261 addNVVMMetadata(GV,
"texture", 1);
266 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
276 if (FD->
hasAttr<DeviceKernelAttr>() || FD->
hasAttr<CUDAGlobalAttr>()) {
279 F->addFnAttr(llvm::Attribute::NoInline);
280 if (FD->
hasAttr<CUDAGlobalAttr>()) {
281 for (
auto IV : llvm::enumerate(FD->
parameters()))
282 if (IV.value()->hasAttr<CUDAGridConstantAttr>())
283 F->addParamAttr(IV.index(),
284 llvm::Attribute::get(F->getContext(),
285 llvm::NVVMAttr::GridConstant));
287 if (CUDALaunchBoundsAttr *Attr = FD->
getAttr<CUDALaunchBoundsAttr>())
293void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::GlobalValue *GV,
294 StringRef Name,
int Operand) {
295 llvm::Module *M = GV->getParent();
299 llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata(
"nvvm.annotations");
301 SmallVector<llvm::Metadata *, 5> MDVals = {
302 llvm::ConstantAsMetadata::get(GV), llvm::MDString::get(Ctx, Name),
303 llvm::ConstantAsMetadata::get(
304 llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), Operand))};
307 MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
310bool NVPTXTargetCodeGenInfo::shouldEmitStaticExternCAliases()
const {
314void NVPTXTargetCodeGenInfo::setTargetAtomicMetadata(
315 CodeGenFunction &CGF, llvm::Instruction &AtomicInst,
316 const AtomicExpr *AE)
const {
322StringRef NVPTXTargetCodeGenInfo::getLLVMSyncScopeStr(
323 const LangOptions &LangOpts,
SyncScope Scope,
324 llvm::AtomicOrdering Ordering)
const {
325 return *llvm::getAtomicScopeIRString(getABIInfo().getTarget().
getTriple(),
330NVPTXTargetCodeGenInfo::getNullPointer(
const CodeGen::CodeGenModule &CGM,
331 llvm::PointerType *PT,
334 if (PT->getAddressSpace() != Ctx.getTargetAddressSpace(LangAS::opencl_local))
335 return llvm::ConstantPointerNull::get(PT);
337 auto NPT = llvm::PointerType::get(
338 PT->getContext(), Ctx.getTargetAddressSpace(LangAS::opencl_generic));
339 return llvm::ConstantExpr::getAddrSpaceCast(
340 llvm::ConstantPointerNull::get(NPT), PT);
345 const CUDALaunchBoundsAttr *
Attr,
346 int32_t *MaxThreadsVal,
347 int32_t *MinBlocksVal,
348 int32_t *MaxClusterRankVal) {
349 llvm::APSInt MaxThreads(32);
350 MaxThreads =
Attr->getMaxThreads()->EvaluateKnownConstInt(
getContext());
351 if (MaxThreads > 0) {
353 *MaxThreadsVal = MaxThreads.getExtValue();
355 F->addFnAttr(llvm::NVVMAttr::MaxNTID,
356 llvm::utostr(MaxThreads.getExtValue()));
362 if (
Attr->getMinBlocks()) {
363 llvm::APSInt MinBlocks(32);
364 MinBlocks =
Attr->getMinBlocks()->EvaluateKnownConstInt(
getContext());
367 *MinBlocksVal = MinBlocks.getExtValue();
369 F->addFnAttr(llvm::NVVMAttr::MinCTASm,
370 llvm::utostr(MinBlocks.getExtValue()));
373 if (
Attr->getMaxBlocks()) {
374 llvm::APSInt MaxBlocks(32);
375 MaxBlocks =
Attr->getMaxBlocks()->EvaluateKnownConstInt(
getContext());
377 if (MaxClusterRankVal)
378 *MaxClusterRankVal = MaxBlocks.getExtValue();
380 F->addFnAttr(llvm::NVVMAttr::MaxClusterRank,
381 llvm::utostr(MaxBlocks.getExtValue()));
386std::unique_ptr<TargetCodeGenInfo>
388 return std::make_unique<NVPTXTargetCodeGenInfo>(CGM.
getTypes());
static void setCUDAKernelCallingConvention(CanQualType &funcTy, CIRGenModule &cgm, const FunctionDecl *fd)
Set calling convention for CUDA/HIP kernel.
static StringRef getTriple(const Command &Job)
Provides definitions for the atomic synchronization scopes.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const TargetInfo & getTargetInfo() const
Attr - This represents one attribute.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
ABIArgInfo & getReturnInfo()
unsigned getCallingConvention() const
getCallingConvention - Return the user specified calling convention, which has been translated into a...
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
void setEffectiveCallingConvention(unsigned Value)
unsigned getNumRequiredArgs() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
This class organizes the cross-function state that is used while generating LLVM code.
void handleCUDALaunchBoundsAttr(llvm::Function *F, const CUDALaunchBoundsAttr *A, int32_t *MaxThreadsVal=nullptr, int32_t *MinBlocksVal=nullptr, int32_t *MaxClusterRankVal=nullptr)
Emit the IR encoding to attach the CUDA launch bounds attribute to F.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
AtomicOptions getAtomicOpts()
Get the current Atomic options.
ASTContext & getContext() const
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
ArrayRef< ParmVarDecl * > parameters() const
ExtInfo withCallingConv(CallingConv cc) const
ExtInfo getExtInfo() const
A (possibly-)qualified type.
virtual bool hasInt128Type() const
Determine whether the __int128 type is supported on this target.
virtual bool hasFloat16Type() const
Determine whether the _Float16 type is supported on this target.
virtual bool hasFloat128Type() const
Determine whether the __float128 type is supported on this target.
bool isFloat16Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isScalarType() const
bool isFloat128Type() const
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isRealFloatingType() const
Floating point categories.
const T * getAs() const
Member-template getAs<specific type>'.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
std::unique_ptr< TargetCodeGenInfo > createNVPTXTargetCodeGenInfo(CodeGenModule &CGM)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
void addAtomicIgnoreDenormalModeMetadata(CodeGenFunction &CGF, llvm::Instruction &AtomicInst, bool AllowHalf=false)
Attach !atomic.ignore.denormal.mode to AtomicInst, if it is an atomicrmw the metadata is meaningful f...
bool isAggregateTypeForABI(QualType T)
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
Top level wrappers for InstallAPI frontend operations.
const FunctionProtoType * T
llvm::AtomicScope getAtomicScope(SyncScope S)
Collapses a clang sync scope onto the target-neutral llvm::AtomicScope.
SyncScope
Defines sync scope values used internally by clang.
U cast(CodeGen::Address addr)
bool getOption(AtomicOptionKind Kind) const