107#include <type_traits>
112#define DEPOTNAME "__local_depot"
146 unsigned numSymbols()
const {
return Symbols.size(); }
148 bool allSymbolsAligned(
unsigned ptrSize)
const {
150 [=](
unsigned pos) {
return pos % ptrSize == 0; });
155 std::vector<unsigned char> buffer;
167 const NVPTXAsmPrinter &AP;
168 const bool EmitGeneric;
171 AggBuffer(
unsigned Size,
const NVPTXAsmPrinter &AP)
173 EmitGeneric(AP.EmitGeneric) {}
175 unsigned getBufferSize()
const {
return Size; }
178 unsigned getCurpos()
const {
return curpos; }
182 void addBytes(
const unsigned char *Ptr,
unsigned Num,
unsigned Bytes) {
186 addZeros(Bytes - Num);
191 buffer[curpos] = Byte;
195 void addZeros(
unsigned Num) {
196 for ([[maybe_unused]]
unsigned _ :
llvm::seq(Num)) {
203 Symbols.push_back(GVar);
204 SymbolsBeforeStripping.
push_back(GVarBeforeStripping);
214 friend class AggBuffer;
219 StringRef getPassName()
const override {
return "NVPTX Assembly Printer"; }
226 void emitStartOfAsmFile(
Module &M)
override;
228 void emitFunctionEntryLabel()
override;
229 void emitFunctionBodyStart()
override;
230 void emitFunctionBodyEnd()
override;
241 unsigned getVirtualRegisterNumber(
Register Reg)
const;
244 const char *Modifier =
nullptr);
247 void emitGlobals(
const Module &M);
256 void emitCallPrototype(
const CallBase &CB,
unsigned UniqueCallSite,
262 template <
typename T>
bool shouldEmitPTXNoReturn(
const T &V)
const {
263 static_assert(std::is_same_v<Function, T> || std::is_base_of_v<CallBase, T>,
264 "expected a function or a call site");
267 if (!NTM.getSubtargetImpl()->hasNoReturn())
270 if (!V.doesNotReturn() || !V.getFunctionType()->getReturnType()->isVoidTy())
273 if constexpr (std::is_same_v<Function, T>)
286 bool ProcessingGeneric)
const;
295 bool doInitialization(
Module &M)
override;
296 bool doFinalization(
Module &M)
override;
311 VRegRCMap VRegMapping;
314 std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
321 bool EmitInitializer);
323 std::string getPTXFundamentalTypeStr(
Type *Ty,
bool =
true)
const;
326 void bufferLEByte(
const Constant *CPV,
int Bytes, AggBuffer *aggBuffer);
327 void bufferAggregateConstant(
const Constant *CV, AggBuffer *aggBuffer);
328 void bufferAggregateConstVec(
const ConstantVector *CV, AggBuffer *aggBuffer);
350 const bool EmitGeneric;
353 NVPTXAsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
365 std::string getVirtualRegisterName(
Register Reg)
const;
367 const MCSymbol *getFunctionFrameSymbol()
const override;
378 assert(V.hasName() &&
"Found texture variable with no name");
383 assert(V.hasName() &&
"Found surface variable with no name");
388 assert(V.hasName() &&
"Found sampler variable with no name");
410 if (SP->getUnit()->isDebugDirectivesOnly() || SP->getUnit()->isNoDebug())
420discoverDependentGlobals(
const Value *V,
421 SmallVectorImpl<const GlobalVariable *> &Globals,
422 SmallPtrSetImpl<const GlobalVariable *> &Seen) {
424 if (Seen.
insert(GV).second)
437 discoverDependentGlobals(
GEP->getPointerOperand(), Globals, Seen);
442 for (
const auto &O :
U->operands())
443 discoverDependentGlobals(O, Globals, Seen);
446struct GlobalVariableDependencyNode {
447 const GlobalVariable *GV =
nullptr;
448 unsigned ModuleOrder = 0;
452class GlobalVariableDependencyGraph {
455 GlobalVariableDependencyNode SyntheticRoot;
458 std::map<const GlobalVariable *, GlobalVariableDependencyNode> Nodes;
461 explicit GlobalVariableDependencyGraph(
const Module &M) {
462 unsigned ModuleOrder = 0;
463 for (
const GlobalVariable &GV :
M.globals()) {
464 GlobalVariableDependencyNode &
Node = Nodes.try_emplace(&GV).first->second;
466 Node.ModuleOrder = ModuleOrder++;
467 SyntheticRoot.Dependencies.push_back(&Node);
470 for (
auto &[GV, Node] : Nodes) {
472 SmallPtrSet<const GlobalVariable *, 4> Seen;
473 for (
const Use &Operand : GV->operands())
474 discoverDependentGlobals(Operand, Dependencies, Seen);
476 for (
const GlobalVariable *Dependency : Dependencies) {
477 auto It = Nodes.find(Dependency);
478 if (It != Nodes.end())
479 Node.Dependencies.push_back(&It->second);
484 const GlobalVariableDependencyNode *getEntryNode()
const {
485 return &SyntheticRoot;
489struct GlobalVariableDependencyGraphTraits {
490 using NodeRef =
const GlobalVariableDependencyNode *;
491 using ChildIteratorType =
494 static NodeRef getEntryNode(NodeRef Node) {
return Node; }
495 static ChildIteratorType child_begin(NodeRef Node) {
496 return Node->Dependencies.begin();
498 static ChildIteratorType child_end(NodeRef Node) {
499 return Node->Dependencies.end();
503using GlobalVariableSCCIterator =
504 scc_iterator<
const GlobalVariableDependencyNode *,
505 GlobalVariableDependencyGraphTraits>;
507static bool shouldSkipModuleLevelGlobal(
const GlobalVariable &GV) {
513static bool isForwardDeclarableGlobal(
const GlobalVariable *GVar) {
514 if (shouldSkipModuleLevelGlobal(*GVar) || GVar->
isDeclaration() ||
535 const DenseSet<const GlobalVariableDependencyNode *> &ForwardDeclared) {
536 using Node = GlobalVariableDependencyNode;
538 DenseSet<const Node *> SCCSet;
541 DenseMap<const Node *, unsigned> DependencyCount;
542 DenseMap<const Node *, SmallVector<const Node *, 4>> Dependents;
543 std::set<std::pair<unsigned, const Node *>>
Ready;
547 for (
const Node *
N : SCC) {
548 unsigned &
Count = DependencyCount[
N];
549 for (
const Node *Dependency :
N->Dependencies) {
550 if (!SCCSet.
count(Dependency) || ForwardDeclared.
count(Dependency))
553 Dependents[Dependency].push_back(
N);
556 Ready.emplace(
N->ModuleOrder,
N);
560 while (!
Ready.empty()) {
565 auto It = Dependents.
find(
N);
566 if (It == Dependents.
end())
568 for (
const Node *Dependent : It->second) {
569 assert(DependencyCount[Dependent] &&
"Dependency already satisfied");
570 if (--DependencyCount[Dependent] == 0)
571 Ready.emplace(Dependent->ModuleOrder, Dependent);
575 if (Order.
size() !=
SCC.size())
583 NVPTX_MC::verifyInstructionPredicates(
MI->getOpcode(),
584 getSubtargetInfo().getFeatureBits());
587 lowerToMCInst(
MI, Inst);
588 EmitToStreamer(*OutStreamer, Inst);
591void NVPTXAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
593 for (
const auto MO :
MI->operands())
597MCOperand NVPTXAsmPrinter::lowerOperand(
const MachineOperand &MO) {
627 case Type::BFloatTyID:
630 case Type::FloatTyID:
633 case Type::DoubleTyID:
642static NVPTX::VirtualRegisterKind
644 if (RC == &NVPTX::B1RegClass)
646 if (RC == &NVPTX::B16RegClass)
648 if (RC == &NVPTX::B32RegClass)
650 if (RC == &NVPTX::B64RegClass)
652 if (RC == &NVPTX::B128RegClass)
657unsigned NVPTXAsmPrinter::getVirtualRegisterNumber(
Register Reg)
const {
659 assert(It != VRegMapping.
end() &&
"Bad register class");
661 const unsigned Num = It->second.lookup(
Reg);
662 assert(Num &&
"Bad virtual register");
666MCRegister NVPTXAsmPrinter::encodeVirtualRegister(
Register Reg) {
671 const unsigned Num = getVirtualRegisterNumber(
Reg);
672 assert(Num <= NVPTX::VirtualRegisterNumMask &&
673 "Too many virtual registers");
674 return (
static_cast<unsigned>(Kind) << NVPTX::VirtualRegisterKindShift) |
680 assert(
Reg.
id() <= NVPTX::VirtualRegisterNumMask &&
681 "Physical register would decode as a virtual register");
685MCOperand NVPTXAsmPrinter::GetSymbolRef(
const MCSymbol *Symbol) {
691void NVPTXAsmPrinter::printReturnValStr(
const Function *
F, raw_ostream &O) {
692 const DataLayout &
DL = getDataLayout();
693 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
696 Type *Ty =
F->getReturnType();
703 auto PrintScalarRetVal = [&](
unsigned Size) {
707 const unsigned TotalSize =
DL.getTypeAllocSize(Ty);
708 const Align RetAlignment =
710 O <<
".param .align " << RetAlignment.
value() <<
" .b8 func_retval0["
715 PrintScalarRetVal(ITy->getBitWidth());
717 PrintScalarRetVal(TLI->getPointerTy(
DL).getSizeInBits());
726 printReturnValStr(&
F, O);
729void NVPTXAsmPrinter::emitCallPrototype(
const CallBase &CB,
730 unsigned UniqueCallSite,
731 raw_ostream &O)
const {
732 const DataLayout &
DL = getDataLayout();
733 const NVPTXSubtarget &STI = MF->
getSubtarget<NVPTXSubtarget>();
735 const auto PtrVT = TLI->getPointerTy(
DL);
738 O <<
"prototype_" << UniqueCallSite <<
" : .callprototype ";
745 const Align RetAlign =
747 O <<
".param .align " << RetAlign.
value() <<
" .b8 _["
748 <<
DL.getTypeAllocSize(RetTy) <<
"]";
752 size = ITy->getBitWidth();
755 "Floating point type expected here");
763 O <<
".param .b" <<
size <<
" _";
765 O <<
".param .b" << PtrVT.getSizeInBits() <<
" _";
773 auto MakeArg = [&](
const unsigned I) {
779 &CB, ETy,
I + AttributeList::FirstArgIndex,
DL);
781 O <<
".param .align " << ParamByValAlign.
value() <<
" .b8 _["
782 <<
DL.getTypeAllocSize(ETy) <<
"]";
789 O <<
".param .align " << ParamAlign.
value() <<
" .b8 _["
790 <<
DL.getTypeAllocSize(Ty) <<
"]";
798 sz = PtrVT.getSizeInBits();
802 O <<
".param .b" << sz <<
" _";
806 const unsigned NumArgs = FTy->getNumParams();
816 if (FTy->isVarArg() && CB.
arg_size() > NumArgs)
817 O << (NonEmptyArgs.empty() ?
"" :
",") <<
" .param .align "
821 if (shouldEmitPTXNoReturn(CB))
826void NVPTXAsmPrinter::emitJumpTable(
const MachineJumpTableEntry &MJT,
827 unsigned MJTI)
const {
828 OutStreamer->emitLabel(GetJTISymbol(MJTI));
830 if (MJT.
MBBs.empty())
835 return MBB->getSymbol();
837 getTargetStreamer()->emitBranchTargetsDirective(Targets);
842bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
843 const MachineBasicBlock &
MBB)
const {
844 const MachineLoopInfo *LI = GetMLI(*MF);
845 assert(LI &&
"NVPTXAsmPrinter requires MachineLoopInfo");
858 if (
const BasicBlock *PBB = PMBB->getBasicBlock()) {
860 PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
863 if (MDNode *UnrollCountMD =
875void NVPTXAsmPrinter::emitBasicBlockStart(
const MachineBasicBlock &
MBB) {
877 if (isLoopHeaderOfNoUnroll(
MBB))
878 getTargetStreamer()->emitPragmaDirective(
"nounroll");
881void NVPTXAsmPrinter::emitFunctionEntryLabel() {
882 SmallString<128> Str;
883 raw_svector_ostream
O(Str);
885 if (!GlobalsEmitted) {
887 GlobalsEmitted =
true;
893 emitLinkageDirective(
F, O);
898 printReturnValStr(*MF, O);
901 CurrentFnSym->print(O, MAI);
903 emitFunctionParamList(
F, O);
907 emitKernelFunctionDirectives(*
F, O);
909 if (shouldEmitPTXNoReturn(*
F))
912 OutStreamer->emitRawText(
O.str());
916 OutStreamer->emitRawText(StringRef(
"{\n"));
917 setAndEmitFunctionVirtualRegisters(*MF);
918 encodeDebugInfoRegisterNumbers(*MF);
930 OutStreamer->emitRawText(StringRef(
"}\n"));
934void NVPTXAsmPrinter::emitFunctionBodyStart() {
935 SmallString<128> Str;
936 raw_svector_ostream
O(Str);
939 const auto *MFI = MF->
getInfo<NVPTXMachineFunctionInfo>();
940 for (
const auto &[Id, CB] : MFI->getCallPrototypes())
941 emitCallPrototype(*CB, Id, O);
943 OutStreamer->emitRawText(
O.str());
946 for (
const auto &[Idx, JT] :
enumerate(MJTI->getJumpTables()))
947 emitJumpTable(JT, Idx);
950void NVPTXAsmPrinter::emitFunctionBodyEnd() {
954const MCSymbol *NVPTXAsmPrinter::getFunctionFrameSymbol()
const {
955 return OutContext.getOrCreateSymbol(
DEPOTNAME + Twine(getFunctionNumber()));
958void NVPTXAsmPrinter::emitImplicitDef(
const MachineInstr *
MI)
const {
961 OutStreamer->AddComment(Twine(
"implicit-def: ") +
962 getVirtualRegisterName(RegNo));
964 OutStreamer->AddComment(Twine(
"implicit-def: ") +
966 OutStreamer->addBlankLine();
969void NVPTXAsmPrinter::emitKernelFunctionDirectives(
const Function &
F,
970 raw_ostream &O)
const {
976 O <<
formatv(
".reqntid {0:$[, ]}\n",
981 O <<
formatv(
".maxntid {0:$[, ]}\n",
985 O <<
".minnctapersm " << *Mincta <<
"\n";
988 O <<
".maxnreg " << *Maxnreg <<
"\n";
992 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
993 const NVPTXSubtarget *STI = &NTM.
getSubtarget<NVPTXSubtarget>(
F);
995 if (STI->hasFeature(NVPTX::SM90)) {
1001 if (!BlocksAreClusters)
1002 O <<
".explicitcluster\n";
1004 if (ClusterDim[0] != 0) {
1006 "cluster_dim_x != 0 implies cluster_dim_y and cluster_dim_z "
1007 "should be non-zero as well");
1009 O <<
formatv(
".reqnctapercluster {0:$[, ]}\n",
1013 "cluster_dim_x == 0 implies cluster_dim_y and cluster_dim_z "
1014 "should be 0 as well");
1018 if (BlocksAreClusters) {
1019 LLVMContext &Ctx =
F.getContext();
1021 Ctx.
diagnose(DiagnosticInfoUnsupported(
1022 F,
"blocksareclusters requires reqntid and cluster_dim attributes",
1023 F.getSubprogram()));
1024 else if (!STI->hasFeature(NVPTX::PTX90))
1025 Ctx.
diagnose(DiagnosticInfoUnsupported(
1026 F,
"blocksareclusters requires PTX version >= 9.0",
1027 F.getSubprogram()));
1029 O <<
".blocksareclusters\n";
1033 O <<
".maxclusterrank " << *Maxclusterrank <<
"\n";
1037std::string NVPTXAsmPrinter::getVirtualRegisterName(
Register Reg)
const {
1041 raw_string_ostream(Name) << NVPTX::getVirtualRegisterPrefix(Kind)
1042 << getVirtualRegisterNumber(
Reg);
1046void NVPTXAsmPrinter::emitAliasDeclaration(
const GlobalAlias *GA,
1051 "NVPTX aliasee must be a non-kernel function definition");
1057 emitDeclarationWithName(
F, getSymbol(GA), O);
1060void NVPTXAsmPrinter::emitDeclaration(
const Function *
F, raw_ostream &O) {
1061 emitDeclarationWithName(
F, getSymbol(
F), O);
1064void NVPTXAsmPrinter::emitDeclarationWithName(
const Function *
F, MCSymbol *S,
1066 emitLinkageDirective(
F, O);
1071 printReturnValStr(
F, O);
1074 emitFunctionParamList(
F, O);
1076 if (shouldEmitPTXNoReturn(*
F))
1086 return GV->
getName() !=
"llvm.used";
1088 for (
const User *U :
C->users())
1098 if (OtherGV->getName() ==
"llvm.used")
1102 if (
const Function *CurFunc =
I->getFunction()) {
1103 if (OneFunc && (CurFunc != OneFunc))
1144 for (
const User *U :
C->users()) {
1149 if (
const Function *Caller =
I->getFunction())
1157void NVPTXAsmPrinter::emitDeclarations(
const Module &M, raw_ostream &O) {
1158 SmallPtrSet<const Function *, 32> SeenSet;
1160 if (
F.getAttributes().hasFnAttr(
"nvptx-libcall-callee")) {
1161 emitDeclaration(&
F, O);
1165 if (
F.isDeclaration()) {
1168 if (
F.getIntrinsicID())
1172 if (
F.isIntrinsic()) {
1173 LLVMContext &Ctx =
F.getContext();
1174 Ctx.
diagnose(DiagnosticInfoUnsupported(
1175 F,
"unknown intrinsic '" +
F.getName() +
1176 "' cannot be lowered by the NVPTX backend"));
1179 emitDeclaration(&
F, O);
1182 for (
const User *U :
F.users()) {
1188 emitDeclaration(&
F, O);
1194 emitDeclaration(&
F, O);
1209 emitDeclaration(&
F, O);
1215 for (
const GlobalAlias &GA :
M.aliases())
1216 emitAliasDeclaration(&GA, O);
1219void NVPTXAsmPrinter::emitStartOfAsmFile(
Module &M) {
1223 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1227 emitHeader(M, *STI);
1231DwarfDebug *NVPTXAsmPrinter::createDwarfDebug() {
1232 return new NVPTXDwarfDebug(
this);
1235bool NVPTXAsmPrinter::doInitialization(
Module &M) {
1236 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1238 if (
M.alias_size() &&
1239 (!STI.hasFeature(NVPTX::PTX63) || !STI.hasFeature(NVPTX::SM30)))
1245 GlobalsEmitted =
false;
1250void NVPTXAsmPrinter::emitGlobals(
const Module &M) {
1251 SmallString<128> Str2;
1252 raw_svector_ostream OS2(Str2);
1254 emitDeclarations(M, OS2);
1256 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1264 GlobalVariableDependencyGraph DependencyGraph(M);
1265 for (GlobalVariableSCCIterator
I =
1266 GlobalVariableSCCIterator::begin(DependencyGraph.getEntryNode());
1267 !
I.isAtEnd(); ++
I) {
1272 if (!
SCC.front()->GV) {
1273 assert(
SCC.size() == 1 &&
"Synthetic root must be in its own SCC");
1278 return LHS->ModuleOrder <
RHS->ModuleOrder;
1281 const bool IsCyclic =
I.hasCycle();
1282 DenseSet<const GlobalVariableDependencyNode *> ForwardDeclared;
1284 for (
const auto *Node : SCC)
1285 if (isForwardDeclarableGlobal(
Node->GV))
1286 ForwardDeclared.
insert(Node);
1290 IsCyclic ? orderDefinitionsInSCC(SCC, ForwardDeclared)
1293 for (
const auto *Node : SCC) {
1294 if (!ForwardDeclared.
count(Node))
1297 emitPTXGlobalVariableDefinition(
Node->GV, OS2, STI,
1302 for (
const GlobalVariable *GV : OrderedGlobals)
1303 printModuleLevelGV(GV, OS2,
false, STI);
1308 OutStreamer->emitRawText(OS2.str());
1311void NVPTXAsmPrinter::emitGlobalAlias(
const Module &M,
const GlobalAlias &GA) {
1312 getTargetStreamer()->emitAliasDirective(getSymbol(&GA),
1316NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer()
const {
1317 return static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1322 switch(
CU->getEmissionKind()) {
1335void NVPTXAsmPrinter::emitHeader(
Module &M,
const NVPTXSubtarget &STI) {
1336 auto *TS = getTargetStreamer();
1341 TS->emitVersionDirective(PTXVersion);
1343 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1346 TS->emitTargetDirective(STI.
getTargetName(), TexModeIndependent,
1348 TS->emitAddressSizeDirective(
M.getDataLayout().getPointerSizeInBits());
1351bool NVPTXAsmPrinter::doFinalization(
Module &M) {
1354 if (!GlobalsEmitted) {
1356 GlobalsEmitted =
true;
1365 static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1368 TS->closeLastSection();
1370 TS->emitEmptySectionDirective(
".debug_macinfo");
1374 TS->outputDwarfFileDirectives();
1392void NVPTXAsmPrinter::emitLinkageDirective(
const GlobalValue *V,
1394 if (
static_cast<NVPTXTargetMachine &
>(TM).getDrvInterface() == NVPTX::CUDA) {
1395 if (
V->hasExternalLinkage()) {
1398 else if (
V->isDeclaration())
1402 }
else if (
V->hasAppendingLinkage()) {
1404 "' has unsupported appending linkage type");
1405 }
else if (!
V->hasInternalLinkage() && !
V->hasPrivateLinkage()) {
1411void NVPTXAsmPrinter::printModuleLevelGV(
const GlobalVariable *GVar,
1412 raw_ostream &O,
bool ProcessDemoted,
1413 const NVPTXSubtarget &STI) {
1415 if (shouldSkipModuleLevelGlobal(*GVar))
1434 if (OpaqueType == PTXOpaqueType::Texture) {
1439 if (OpaqueType == PTXOpaqueType::Surface) {
1448 emitPTXGlobalVariable(GVar, O, STI);
1453 if (OpaqueType == PTXOpaqueType::Sampler) {
1456 const Constant *Initializer =
nullptr;
1459 const ConstantInt *CI =
nullptr;
1470 O <<
"addr_mode_" << i <<
" = ";
1476 O <<
"clamp_to_border";
1479 O <<
"clamp_to_edge";
1490 O <<
"filter_mode = ";
1505 O <<
", force_unnormalized_coords = 1";
1525 const Function *DemotedFunc =
nullptr;
1527 O <<
"// " << GVar->
getName() <<
" has been demoted\n";
1528 localDecls[DemotedFunc].push_back(GVar);
1532 emitPTXGlobalVariableDefinition(GVar, O, STI,
true);
1536void NVPTXAsmPrinter::emitPTXGlobalVariableDefinition(
1537 const GlobalVariable *GVar, raw_ostream &O,
const NVPTXSubtarget &STI,
1538 bool EmitInitializer) {
1539 const DataLayout &
DL = getDataLayout();
1547 if (!STI.hasFeature(NVPTX::PTX40) || !STI.hasFeature(NVPTX::SM30))
1549 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1550 O <<
" .attribute(.managed)";
1554 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1563 O << getPTXFundamentalTypeStr(ETy,
false);
1565 getSymbol(GVar)->print(O, MAI);
1576 printScalarConstant(Initializer, O);
1585 "' is not allowed in addrspace(" +
1596 case Type::IntegerTyID:
1597 case Type::FP128TyID:
1598 case Type::StructTyID:
1599 case Type::ArrayTyID:
1600 case Type::FixedVectorTyID: {
1601 const uint64_t ElementSize =
DL.getTypeStoreSize(ETy);
1609 AggBuffer aggBuffer(ElementSize, *
this);
1610 bufferAggregateConstant(Initializer, &aggBuffer);
1611 if (aggBuffer.numSymbols()) {
1612 const unsigned int ptrSize = MAI.getCodePointerSize();
1613 if (ElementSize % ptrSize ||
1614 !aggBuffer.allSymbolsAligned(ptrSize)) {
1618 "initialized packed aggregate with pointers '" +
1620 "' requires at least PTX ISA version 7.1");
1622 getSymbol(GVar)->print(O, MAI);
1623 O <<
"[" << ElementSize <<
"]";
1624 if (EmitInitializer) {
1626 aggBuffer.printBytes(O);
1630 O <<
" .u" << ptrSize * 8 <<
" ";
1631 getSymbol(GVar)->print(O, MAI);
1632 O <<
"[" << ElementSize / ptrSize <<
"]";
1633 if (EmitInitializer) {
1635 aggBuffer.printWords(O);
1641 getSymbol(GVar)->print(O, MAI);
1642 O <<
"[" << ElementSize <<
"]";
1643 if (EmitInitializer) {
1645 aggBuffer.printBytes(O);
1651 getSymbol(GVar)->print(O, MAI);
1653 O <<
"[" << ElementSize <<
"]";
1657 getSymbol(GVar)->print(O, MAI);
1659 O <<
"[" << ElementSize <<
"]";
1669void NVPTXAsmPrinter::AggBuffer::printSymbol(
unsigned nSym, raw_ostream &os) {
1670 const Value *
v = Symbols[nSym];
1671 const Value *v0 = SymbolsBeforeStripping[nSym];
1676 bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
1679 Name->print(os, AP.MAI);
1682 Name->print(os, AP.MAI);
1685 const MCExpr *Expr = AP.lowerConstantForGV(CExpr,
false);
1686 AP.printMCExpr(*Expr, os);
1691void NVPTXAsmPrinter::AggBuffer::printBytes(raw_ostream &os) {
1692 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1697 unsigned int InitializerCount =
Size;
1700 if (numSymbols() == 0)
1701 while (InitializerCount >= 1 && !buffer[InitializerCount - 1])
1704 symbolPosInBuffer.push_back(InitializerCount);
1705 unsigned int nSym = 0;
1706 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1707 for (
unsigned int pos = 0; pos < InitializerCount;) {
1710 if (pos != nextSymbolPos) {
1711 os << (
unsigned int)buffer[pos];
1718 std::string symText;
1719 llvm::raw_string_ostream oss(symText);
1720 printSymbol(nSym, oss);
1721 for (
unsigned i = 0; i < ptrSize; ++i) {
1725 os <<
"(" << symText <<
")";
1728 nextSymbolPos = symbolPosInBuffer[++nSym];
1729 assert(nextSymbolPos >= pos);
1733void NVPTXAsmPrinter::AggBuffer::printWords(raw_ostream &os) {
1734 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1735 symbolPosInBuffer.push_back(
Size);
1736 unsigned int nSym = 0;
1737 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1738 assert(nextSymbolPos % ptrSize == 0);
1739 for (
unsigned int pos = 0; pos <
Size; pos += ptrSize) {
1742 if (pos == nextSymbolPos) {
1743 printSymbol(nSym, os);
1744 nextSymbolPos = symbolPosInBuffer[++nSym];
1745 assert(nextSymbolPos % ptrSize == 0);
1746 assert(nextSymbolPos >= pos + ptrSize);
1747 }
else if (ptrSize == 4)
1754void NVPTXAsmPrinter::emitDemotedVars(
const Function *
F, raw_ostream &O) {
1755 auto It = localDecls.find(
F);
1756 if (It == localDecls.end())
1761 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1764 for (
const GlobalVariable *GV : GVars) {
1765 O <<
"\t// demoted variable\n\t";
1766 printModuleLevelGV(GV, O,
true, STI);
1770void NVPTXAsmPrinter::emitPTXAddressSpace(
unsigned int AddressSpace,
1771 raw_ostream &O)
const {
1793NVPTXAsmPrinter::getPTXFundamentalTypeStr(
Type *Ty,
bool useB4PTR)
const {
1795 case Type::IntegerTyID: {
1799 if (NumBits <= 64) {
1800 std::string
name =
"u";
1806 case Type::BFloatTyID:
1807 case Type::HalfTyID:
1811 case Type::FloatTyID:
1813 case Type::DoubleTyID:
1815 case Type::PointerTyID: {
1817 assert((PtrSize == 64 || PtrSize == 32) &&
"Unexpected pointer size");
1835void NVPTXAsmPrinter::emitPTXGlobalVariable(
const GlobalVariable *GVar,
1837 const NVPTXSubtarget &STI) {
1838 const DataLayout &
DL = getDataLayout();
1846 if (!STI.hasFeature(NVPTX::PTX40) || !STI.hasFeature(NVPTX::SM30))
1848 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1850 O <<
" .attribute(.managed)";
1853 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1858 getSymbol(GVar)->print(O, MAI);
1864 O <<
" ." << getPTXFundamentalTypeStr(ETy) <<
" ";
1865 getSymbol(GVar)->print(O, MAI);
1869 int64_t ElementSize = 0;
1876 case Type::StructTyID:
1877 case Type::ArrayTyID:
1878 case Type::FixedVectorTyID:
1879 ElementSize =
DL.getTypeStoreSize(ETy);
1881 getSymbol(GVar)->print(O, MAI);
1893void NVPTXAsmPrinter::emitFunctionParamList(
const Function *
F, raw_ostream &O) {
1894 const DataLayout &
DL = getDataLayout();
1895 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
1897 const NVPTXMachineFunctionInfo *MFI =
1898 MF ? MF->
getInfo<NVPTXMachineFunctionInfo>() : nullptr;
1900 bool IsFirst =
true;
1907 const auto NonEmptyArgs =
1909 return !Arg.getType()->isEmptyTy();
1912 if (NonEmptyArgs.empty() && !
F->isVarArg()) {
1919 for (
const auto &[ParamIndex, Arg] :
enumerate(NonEmptyArgs)) {
1920 Type *Ty = Arg.getType();
1921 const std::string ParamSym = TLI->getParamName(
F, ParamIndex);
1931 if (ArgOpaqueType != PTXOpaqueType::None) {
1937 switch (ArgOpaqueType) {
1938 case PTXOpaqueType::Sampler:
1939 O <<
".samplerref ";
1941 case PTXOpaqueType::Texture:
1944 case PTXOpaqueType::Surface:
1947 case PTXOpaqueType::None:
1955 if (Arg.hasByValAttr()) {
1957 Type *ETy = Arg.getParamByValType();
1958 assert(ETy &&
"Param should have byval type");
1964 const unsigned ParamIdx = Arg.getArgNo() + AttributeList::FirstArgIndex;
1965 const Align OptimalAlign =
1969 O <<
"\t.param .align " << OptimalAlign.
value() <<
" .b8 " << ParamSym
1970 <<
"[" <<
DL.getTypeAllocSize(ETy) <<
"]";
1980 F, Ty, Arg.getArgNo() + AttributeList::FirstArgIndex,
DL);
1982 O <<
"\t.param .align " << OptimalAlign.
value() <<
" .b8 " << ParamSym
1983 <<
"[" <<
DL.getTypeAllocSize(Ty) <<
"]";
1989 unsigned PTySizeInBits = 0;
1992 TLI->getPointerTy(
DL, PTy->getAddressSpace()).getSizeInBits();
1993 assert(PTySizeInBits &&
"Invalid pointer size");
1998 O <<
"\t.param .u" << PTySizeInBits <<
" .ptr";
2000 switch (PTy->getAddressSpace()) {
2017 O <<
" .align " << Arg.getParamAlign().valueOrOne().value() <<
" "
2028 O << getPTXFundamentalTypeStr(Ty);
2029 O <<
" " << ParamSym;
2038 assert(PTySizeInBits &&
"Invalid pointer size");
2039 Size = PTySizeInBits;
2042 O <<
"\t.param .b" <<
Size <<
" " << ParamSym;
2045 if (
F->isVarArg()) {
2049 << TLI->getParamName(
F, -1) <<
"[]";
2055void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
2057 auto *TS = getTargetStreamer();
2062 TS->emitLocalDirective(MFI.
getMaxAlign(), getFunctionFrameSymbol(),
2066 const NVPTXRegisterInfo *NRI =
2070 TS->emitRegDirective(
2071 NRI->getRegSizeInBits(FrameReg, *MRI).getFixedValue(),
2080 Register VR = Register::index2VirtReg(
I);
2083 auto &RCRegMap = VRegMapping[MRI->
getRegClass(VR)];
2084 RCRegMap[VR] = RCRegMap.
size() + 1;
2092 const auto It = VRegMapping.
find(&RC);
2093 if (It == VRegMapping.
end() || It->second.empty())
2096 TS->emitRegDirective(
2097 TRI->getRegSizeInBits(RC).getFixedValue(),
2099 It->second.size() + 1);
2105void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
2107 const NVPTXSubtarget &STI = MF.
getSubtarget<NVPTXSubtarget>();
2117 NRI->addToDebugRegisterMap(
Reg, getVirtualRegisterName(
Reg));
2120void NVPTXAsmPrinter::printFPConstant(
const ConstantFP *Fp,
2121 raw_ostream &O)
const {
2124 unsigned int numHex;
2130 APF.
convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &ignored);
2134 APF.
convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &ignored);
2142void NVPTXAsmPrinter::printScalarConstant(
const Constant *CPV, raw_ostream &O) {
2148 printFPConstant(CFP, O);
2157 if (EmitGeneric && !
isa<Function>(CPV) && !IsNonGenericPointer) {
2159 getSymbol(GVar)->print(O, MAI);
2162 getSymbol(GVar)->print(O, MAI);
2174void NVPTXAsmPrinter::bufferLEByte(
const Constant *CPV,
int Bytes,
2175 AggBuffer *AggBuffer) {
2176 const DataLayout &
DL = getDataLayout();
2177 int AllocSize =
DL.getTypeAllocSize(CPV->
getType());
2181 AggBuffer->addZeros(Bytes ? Bytes : AllocSize);
2186 auto AddIntToBuffer = [AggBuffer, Bytes](
const APInt &Val) {
2187 size_t NumBytes = (Val.getBitWidth() + 7) / 8;
2193 for (
unsigned I = 0;
I < NumBytes - 1; ++
I) {
2194 Buf[
I] = Val.extractBitsAsZExtValue(8,
I * 8);
2196 size_t LastBytePosition = (NumBytes - 1) * 8;
2197 size_t LastByteBits = Val.getBitWidth() - LastBytePosition;
2199 Val.extractBitsAsZExtValue(LastByteBits, LastBytePosition);
2200 AggBuffer->addBytes(Buf.data(), NumBytes, Bytes);
2204 case Type::IntegerTyID:
2210 if (
const auto *CI =
2215 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
2216 Value *
V = Cexpr->getOperand(0)->stripPointerCasts();
2217 AggBuffer->addSymbol(V, Cexpr->getOperand(0));
2218 AggBuffer->addZeros(AllocSize);
2225 AggBuffer->addSymbol(Cexpr, Cexpr);
2226 AggBuffer->addZeros(AllocSize);
2232 case Type::HalfTyID:
2233 case Type::BFloatTyID:
2234 case Type::FloatTyID:
2235 case Type::DoubleTyID:
2236 case Type::FP128TyID:
2240 case Type::PointerTyID: {
2242 AggBuffer->addSymbol(GVar, GVar);
2244 const Value *
v = Cexpr->stripPointerCasts();
2245 AggBuffer->addSymbol(v, Cexpr);
2247 AggBuffer->addZeros(AllocSize);
2251 case Type::ArrayTyID:
2252 case Type::FixedVectorTyID:
2253 case Type::StructTyID: {
2257 unsigned StartPos = AggBuffer->getCurpos();
2258 bufferAggregateConstant(CPV, AggBuffer);
2259 unsigned Written = AggBuffer->getCurpos() - StartPos;
2260 unsigned SlotSize = std::max<int>(Bytes, AllocSize);
2261 if (SlotSize > Written)
2262 AggBuffer->addZeros(SlotSize - Written);
2264 AggBuffer->addZeros(Bytes);
2275void NVPTXAsmPrinter::bufferAggregateConstant(
const Constant *CPV,
2276 AggBuffer *aggBuffer) {
2277 const DataLayout &
DL = getDataLayout();
2279 auto ExtendBuffer = [](APInt Val, AggBuffer *Buffer) {
2282 unsigned NumBits = std::min(8u, Val.
getBitWidth() -
I * 8);
2290 for (
unsigned I :
llvm::seq(VTy->getNumElements()))
2299 ExtendBuffer(CI->
getValue(), aggBuffer);
2305 assert(CFP->getType()->isFloatingPointTy() &&
"Expected fp constant!");
2306 if (CFP->getType()->isFP128Ty()) {
2307 ExtendBuffer(CFP->getValueAPF().bitcastToAPInt(), aggBuffer);
2321 bufferAggregateConstVec(CVec, aggBuffer);
2326 for (
unsigned I :
llvm::seq(CDS->getNumElements()))
2327 bufferLEByte(
cast<Constant>(CDS->getElementAsConstant(
I)), 0, aggBuffer);
2336 ?
DL.getStructLayout(ST)->getElementOffset(0) +
2337 DL.getTypeAllocSize(ST)
2338 :
DL.getStructLayout(ST)->getElementOffset(
I + 1);
2339 int Bytes = EndOffset -
DL.getStructLayout(ST)->getElementOffset(
I);
2348void NVPTXAsmPrinter::bufferAggregateConstVec(
const ConstantVector *CV,
2349 AggBuffer *aggBuffer) {
2351 const unsigned BuffSize = aggBuffer->getBufferSize();
2354 if (BuffSize >= NumElems) {
2367 assert(ElemTySize < 8 &&
"Expected sub-byte data type.");
2368 assert(8 % ElemTySize == 0 &&
"Element type size must evenly divide a byte.");
2370 unsigned NumElemsPerByte = 8 / ElemTySize;
2371 unsigned NumCompleteBytes = NumElems / NumElemsPerByte;
2372 unsigned NumTailElems = NumElems % NumElemsPerByte;
2377 auto ConvertSubCVtoInt8 = [
this, &ElemTy](
const ConstantVector *CV,
2378 unsigned Start,
unsigned End,
2379 unsigned NumPaddingZeros = 0) {
2386 if (NumPaddingZeros)
2387 SubCVElems.
append(NumPaddingZeros, ConstantInt::getNullValue(ElemTy));
2393 ConstantInt *MergedElem =
2400 "Cannot lower vector global with unusual element type");
2407 for (
unsigned ByteIdx :
llvm::seq(NumCompleteBytes))
2408 bufferLEByte(ConvertSubCVtoInt8(CV, ByteIdx * NumElemsPerByte,
2409 (ByteIdx + 1) * NumElemsPerByte),
2413 if (NumTailElems > 0)
2414 bufferLEByte(ConvertSubCVtoInt8(CV, NumElems - NumTailElems, NumElems,
2415 NumElemsPerByte - NumTailElems),
2424NVPTXAsmPrinter::lowerConstantForGV(
const Constant *CV,
2425 bool ProcessingGeneric)
const {
2426 MCContext &Ctx = OutContext;
2436 if (ProcessingGeneric)
2446 switch (
CE->getOpcode()) {
2450 case Instruction::AddrSpaceCast: {
2453 if (DstTy->getAddressSpace() == 0)
2459 case Instruction::GetElementPtr: {
2460 const DataLayout &
DL = getDataLayout();
2463 APInt OffsetAI(
DL.getPointerTypeSizeInBits(
CE->getType()), 0);
2466 const MCExpr *
Base = lowerConstantForGV(
CE->getOperand(0),
2471 int64_t
Offset = OffsetAI.getSExtValue();
2476 case Instruction::Trunc:
2482 case Instruction::BitCast:
2483 return lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2485 case Instruction::IntToPtr: {
2486 const DataLayout &
DL = getDataLayout();
2494 return lowerConstantForGV(
Op, ProcessingGeneric);
2499 case Instruction::PtrToInt: {
2500 const DataLayout &
DL = getDataLayout();
2505 Type *Ty =
CE->getType();
2507 const MCExpr *OpExpr = lowerConstantForGV(
Op, ProcessingGeneric);
2511 if (
DL.getTypeAllocSize(Ty) ==
DL.getTypeAllocSize(
Op->getType()))
2517 unsigned InBits =
DL.getTypeAllocSizeInBits(
Op->getType());
2524 case Instruction::Add: {
2525 const MCExpr *
LHS = lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2526 const MCExpr *
RHS = lowerConstantForGV(
CE->getOperand(1), ProcessingGeneric);
2527 switch (
CE->getOpcode()) {
2539 return lowerConstantForGV(
C, ProcessingGeneric);
2543 raw_string_ostream OS(S);
2544 OS <<
"Unsupported expression in static initializer: ";
2545 CE->printAsOperand(OS,
false,
2550void NVPTXAsmPrinter::printMCExpr(
const MCExpr &Expr, raw_ostream &OS)
const {
2551 OutContext.getAsmInfo().printExpr(OS, Expr);
2556bool NVPTXAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
2557 const char *ExtraCode, raw_ostream &O) {
2558 if (ExtraCode && ExtraCode[0]) {
2559 if (ExtraCode[1] != 0)
2562 switch (ExtraCode[0]) {
2576bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
2578 const char *ExtraCode,
2580 if (ExtraCode && ExtraCode[0])
2590void NVPTXAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
2592 const MachineOperand &MO =
MI->getOperand(OpNum);
2596 if (MO.
getReg() == NVPTX::VRDepot)
2597 getFunctionFrameSymbol()->print(O, MAI);
2601 O << getVirtualRegisterName(MO.
getReg());
2614 PrintSymbolOperand(MO, O);
2626void NVPTXAsmPrinter::printMemOperand(
const MachineInstr *
MI,
unsigned OpNum,
2627 raw_ostream &O,
const char *Modifier) {
2630 if (Modifier && strcmp(Modifier,
"add") == 0) {
2634 if (
MI->getOperand(OpNum + 1).isImm() &&
2635 MI->getOperand(OpNum + 1).getImm() == 0)
2646 return !Trimmed.
empty() &&
2647 (std::isalpha(
static_cast<unsigned char>(Trimmed[0])) ||
2654 if (!
MI || !
MI->getDebugLoc())
2656 const DISubprogram *SP =
MI->getMF()->getFunction().getSubprogram();
2660 if (!
DL->getFile() || !
DL->getLine())
2666struct InlineAsmInliningContext {
2668 unsigned FileIA = 0;
2669 unsigned LineIA = 0;
2672 bool hasInlinedAt()
const {
return FuncNameSym !=
nullptr; }
2678static InlineAsmInliningContext
2682 InlineAsmInliningContext Ctx;
2684 if (!InlinedAt || !InlinedAt->getFile() || !NVDD ||
2692 0, InlinedAt->getFile()->getDirectory(),
2693 InlinedAt->getFile()->getFilename(), std::nullopt, std::nullopt, CUID);
2694 Ctx.LineIA = InlinedAt->getLine();
2695 Ctx.ColIA = InlinedAt->getColumn();
2699void NVPTXAsmPrinter::emitInlineAsm(StringRef Str,
const MCSubtargetInfo &STI,
2700 const MCTargetOptions &MCOptions,
2701 const MDNode *LocMDNode,
2703 const MachineInstr *
MI) {
2704 assert(!Str.empty() &&
"Can't emit empty inline asm block");
2705 if (Str.back() == 0)
2706 Str = Str.substr(0, Str.size() - 1);
2708 auto emitAsmStr = [&](StringRef AsmStr) {
2709 emitInlineAsmStart();
2710 OutStreamer->emitRawText(AsmStr);
2711 emitInlineAsmEnd(STI,
nullptr,
MI);
2720 const DIFile *
File =
DL->getFile();
2721 unsigned Line =
DL->getLine();
2722 const unsigned Column =
DL->getColumn();
2723 const unsigned CUID = OutStreamer->getContext().getDwarfCompileUnitID();
2724 const unsigned FileNumber = OutStreamer->emitDwarfFileDirective(
2725 0,
File->getDirectory(),
File->getFilename(), std::nullopt, std::nullopt,
2728 auto *NVDD =
static_cast<NVPTXDwarfDebug *
>(getDwarfDebug());
2729 InlineAsmInliningContext InlineCtx =
2732 SmallVector<StringRef, 16>
Lines;
2733 Str.split(Lines,
'\n');
2734 emitInlineAsmStart();
2735 for (
const StringRef &L : Lines) {
2736 StringRef RTrimmed =
L.rtrim(
'\r');
2738 if (InlineCtx.hasInlinedAt()) {
2739 OutStreamer->emitDwarfLocDirectiveWithInlinedAt(
2740 FileNumber, Line, Column, InlineCtx.FileIA, InlineCtx.LineIA,
2742 File->getFilename());
2744 OutStreamer->emitDwarfLocDirective(FileNumber, Line, Column,
2746 File->getFilename());
2749 OutStreamer->emitRawText(RTrimmed);
2752 emitInlineAsmEnd(STI,
nullptr,
MI);
2755char NVPTXAsmPrinter::ID = 0;
2762LLVMInitializeNVPTXAsmPrinter() {
2783 Printer.runOnMachineFunction(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu next use AMDGPU Next Use Analysis Printer
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool hasDebugInfo(const MachineFunction *MF)
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, uint8_t DefaultVisibility)
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, HexagonAsmPrinter &Printer, bool MustExtend)
Module.h This file contains the declarations for the Module class.
#define DWARF2_FLAG_IS_STMT
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static void emitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)
static StringRef getTextureName(const Value &V)
static const DILocation * getInlineAsmDebugLoc(const MachineInstr *MI)
Returns the DILocation for an inline asm MachineInstr if debug line info should be emitted,...
static bool hasFullDebugInfo(Module &M)
static StringRef getSurfaceName(const Value &V)
static bool canDemoteGlobalVar(const GlobalVariable *GV, Function const *&f)
static StringRef getSamplerName(const Value &V)
static bool useFuncSeen(const Constant *C, const SmallPtrSetImpl< const Function * > &SeenSet)
static NVPTX::VirtualRegisterKind getVirtualRegisterKind(const TargetRegisterClass *RC)
static bool usedInGlobalVarDef(const Constant *C)
static InlineAsmInliningContext getInlineAsmInliningContext(const DILocation *DL, const MachineFunction &MF, NVPTXDwarfDebug *NVDD, MCStreamer &Streamer, unsigned CUID)
Resolves the enhanced-lineinfo inlining context for an inline asm debug location.
static bool isPTXInstruction(StringRef Line)
Returns true if Line begins with an alphabetic character or underscore, indicating it is a PTX instru...
static bool usedInOneFunc(const User *U, Function const *&OneFunc)
static void emitInitialRawDwarfLocDirective(const MachineFunction &MF, DwarfDebug *DD, MCStreamer &OutStreamer)
Emits initial debug location directive.
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
APInt bitcastToAPInt() const
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
unsigned getBitWidth() const
Return the number of bits in the APInt.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
This class is intended to be used as a driving class for all asm writers.
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool doFinalization(Module &M) override
Shut down the asmprinter.
virtual void emitBasicBlockStart(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the start of a basic block.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
unsigned arg_size() const
static LLVM_ABI Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
Constant Vector Declarations.
FixedVectorType * getType() const
Specialize the getType() method to always return a FixedVectorType, which reduces the amount of casti...
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
Subprogram description. Uses SubclassData1.
iterator find(const_arg_type_t< KeyT > Val)
Collects and handles dwarf debug information.
const MachineInstr * emitInitialLocDirective(const MachineFunction &MF, unsigned CUID)
Emits inital debug location directive.
unsigned getNumElements() const
Type * getReturnType() const
DISubprogram * getSubprogram() const
Get the attached subprogram.
LLVM_ABI const GlobalObject * getAliaseeObject() const
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
bool hasLinkOnceLinkage() const
bool hasExternalLinkage() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
bool hasPrivateLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
bool hasWeakLinkage() const
bool hasCommonLinkage() const
bool hasAvailableExternallyLinkage() const
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isLoopHeader(const BlockT *BB) const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
unsigned emitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, std::optional< MD5::MD5Result > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt, unsigned CUID=0)
Associate a filename with a specified logical file number.
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
iterator_range< pred_iterator > predecessors()
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_FPImmediate
Floating-point immediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
A Module instance is used to store all the information related to an LLVM module.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
NVPTX-specific DwarfDebug implementation.
bool isEnhancedLineinfo(const MachineFunction &MF) const
Returns true if the enhanced lineinfo mode (with inlined_at) is active for the given MachineFunction.
MCSymbol * getOrCreateFuncNameSymbol(StringRef LinkageName)
Get or create an MCSymbol in .debug_str for a function's linkage name.
static const NVPTXFloatMCExpr * createConstantBFPHalf(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPHalf(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPSingle(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPDouble(const APFloat &Flt, MCContext &Ctx)
static const NVPTXGenericMCSymbolRefExpr * create(const MCSymbolRefExpr *SymExpr, MCContext &Ctx)
static const char * getRegisterName(MCRegister Reg)
bool checkImageHandleSymbol(StringRef Symbol) const
Check if the symbol has a mapping.
void clearDebugRegisterMap() const
Register getFrameLocalRegister(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
StringRef getTargetName() const
unsigned getMaxRequiredAlignment() const
bool hasMaskOperator() const
const NVPTXTargetLowering * getTargetLowering() const override
unsigned getPTXVersion() const
const NVPTXRegisterInfo * getRegisterInfo() const override
NVPTX::DrvInterface getDrvInterface() const
const NVPTXSubtarget * getSubtargetImpl(const Function &) const override
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Implments NVPTX-specific streamer.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
typename SuperClass::const_iterator const_iterator
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI bool isEmptyTy() const
Return true if this type is empty, that is, it has no elements or all of its elements are empty.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
TypeID getTypeID() const
Return the type id for the type.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
void insert_range(Range &&R)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral ReqNTID("nvvm.reqntid")
constexpr StringLiteral ClusterDim("nvvm.cluster_dim")
constexpr StringLiteral BlocksAreClusters("nvvm.blocksareclusters")
@ CE
Windows NT (Windows on ARM)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ Ready
Emitted to memory, but waiting on transitive dependencies.
std::pair< NodeId, LaneBitmask > NodeRef
NodeAddr< NodeBase * > Node
uint64_t read64le(const void *P)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
bool isManaged(const Value &)
SmallVector< unsigned, 3 > getReqNTID(const Function &)
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
Align getDeviceByValParamAlign(const Function *F, Type *ArgTy, unsigned AttrIdx, const DataLayout &DL)
The .param-space alignment for a byval parameter or call argument: the (possibly promoted) parameter ...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
bool hasBlocksAreClusters(const Function &)
SmallVector< unsigned, 3 > getClusterDim(const Function &)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::optional< unsigned > getMaxNReg(const Function &)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
PTXOpaqueType getPTXOpaqueType(const GlobalVariable &)
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
std::optional< unsigned > getMinCTASm(const Function &)
LLVM_ABI Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
unsigned promoteScalarArgumentSize(unsigned size)
SmallVector< unsigned, 3 > getMaxNTID(const Function &)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool shouldPassAsArray(Type *Ty)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
std::optional< unsigned > getMaxClusterRank(const Function &)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
DWARFExpression::Operation Op
Align getPTXParamAlign(const Function *F, Type *Ty, unsigned AttrIdx, const DataLayout &DL)
Alignment for a function parameter or return value at AttributeList index AttrIdx (FirstArgIndex + ar...
ArrayRef(const T &OneElt) -> ArrayRef< T >
Target & getTheNVPTXTarget64()
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
bool isKernelFunction(const Function &F)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void clearAnnotationCache(const Module *)
LLVM_ABI Constant * ConstantFoldIntegerCast(Constant *C, Type *DestTy, bool IsSigned, const DataLayout &DL)
Constant fold a zext, sext or trunc, depending on IsSigned and whether the DestTy is wider or narrowe...
LLVM_ABI MDNode * GetUnrollMetadata(MDNode *LoopID, StringRef Name)
Given an llvm.loop loop id metadata node, returns the loop hint metadata node with the given name (fo...
LLVM_ABI DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Target & getTheNVPTXTarget32()
MCRegisterClass TargetRegisterClass
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MachineJumpTableEntry - One jump table in the jump table info.
std::vector< MachineBasicBlock * > MBBs
MBBs - The vector of basic blocks from which to create the jump table.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...