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);
254 void emitCallPrototype(
const CallBase &CB,
MCSymbol *PrototypeSymbol)
const;
259 template <
typename T>
bool shouldEmitPTXNoReturn(
const T &V)
const {
260 static_assert(std::is_same_v<Function, T> || std::is_base_of_v<CallBase, T>,
261 "expected a function or a call site");
264 if (!NTM.getSubtargetImpl()->hasNoReturn())
267 if (!V.doesNotReturn() || !V.getFunctionType()->getReturnType()->isVoidTy())
270 if constexpr (std::is_same_v<Function, T>)
283 bool ProcessingGeneric)
const;
292 bool doInitialization(
Module &M)
override;
293 bool doFinalization(
Module &M)
override;
308 VRegRCMap VRegMapping;
311 std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
320 bool EmitInitializer);
322 std::string getPTXFundamentalTypeStr(
Type *Ty)
const;
325 void bufferLEByte(
const Constant *CPV,
int Bytes, AggBuffer *aggBuffer);
326 void bufferAggregateConstant(
const Constant *CV, AggBuffer *aggBuffer);
327 void bufferAggregateConstVec(
const ConstantVector *CV, AggBuffer *aggBuffer);
349 const bool EmitGeneric;
364 std::string getVirtualRegisterName(
Register Reg)
const;
366 const MCSymbol *getFunctionFrameSymbol()
const override;
394 if (SP->getUnit()->isDebugDirectivesOnly() || SP->getUnit()->isNoDebug())
404discoverDependentGlobals(
const Value *V,
405 SmallVectorImpl<const GlobalVariable *> &Globals,
406 SmallPtrSetImpl<const GlobalVariable *> &Seen) {
408 if (Seen.
insert(GV).second)
421 discoverDependentGlobals(
GEP->getPointerOperand(), Globals, Seen);
426 for (
const auto &O :
U->operands())
427 discoverDependentGlobals(O, Globals, Seen);
430struct GlobalVariableDependencyNode {
431 const GlobalVariable *GV =
nullptr;
432 unsigned ModuleOrder = 0;
436class GlobalVariableDependencyGraph {
439 GlobalVariableDependencyNode SyntheticRoot;
442 std::map<const GlobalVariable *, GlobalVariableDependencyNode> Nodes;
445 explicit GlobalVariableDependencyGraph(
const Module &M) {
446 unsigned ModuleOrder = 0;
447 for (
const GlobalVariable &GV :
M.globals()) {
448 GlobalVariableDependencyNode &
Node = Nodes.try_emplace(&GV).first->second;
450 Node.ModuleOrder = ModuleOrder++;
451 SyntheticRoot.Dependencies.push_back(&Node);
454 for (
auto &[GV, Node] : Nodes) {
456 SmallPtrSet<const GlobalVariable *, 4> Seen;
457 for (
const Use &Operand : GV->operands())
458 discoverDependentGlobals(Operand, Dependencies, Seen);
460 for (
const GlobalVariable *Dependency : Dependencies) {
461 auto It = Nodes.find(Dependency);
462 if (It != Nodes.end())
463 Node.Dependencies.push_back(&It->second);
468 const GlobalVariableDependencyNode *getEntryNode()
const {
469 return &SyntheticRoot;
473struct GlobalVariableDependencyGraphTraits {
474 using NodeRef =
const GlobalVariableDependencyNode *;
475 using ChildIteratorType =
478 static NodeRef getEntryNode(NodeRef Node) {
return Node; }
479 static ChildIteratorType child_begin(NodeRef Node) {
480 return Node->Dependencies.begin();
482 static ChildIteratorType child_end(NodeRef Node) {
483 return Node->Dependencies.end();
487using GlobalVariableSCCIterator =
488 scc_iterator<
const GlobalVariableDependencyNode *,
489 GlobalVariableDependencyGraphTraits>;
491static bool shouldSkipModuleLevelGlobal(
const GlobalVariable &GV) {
497static bool isForwardDeclarableGlobal(
const GlobalVariable *GVar) {
498 if (shouldSkipModuleLevelGlobal(*GVar) || GVar->
isDeclaration() ||
519 const DenseSet<const GlobalVariableDependencyNode *> &ForwardDeclared) {
520 using Node = GlobalVariableDependencyNode;
522 DenseSet<const Node *> SCCSet;
525 DenseMap<const Node *, unsigned> DependencyCount;
526 DenseMap<const Node *, SmallVector<const Node *, 4>> Dependents;
527 std::set<std::pair<unsigned, const Node *>>
Ready;
531 for (
const Node *
N : SCC) {
532 unsigned &
Count = DependencyCount[
N];
533 for (
const Node *Dependency :
N->Dependencies) {
534 if (!SCCSet.
count(Dependency) || ForwardDeclared.
count(Dependency))
537 Dependents[Dependency].push_back(
N);
540 Ready.emplace(
N->ModuleOrder,
N);
544 while (!
Ready.empty()) {
549 auto It = Dependents.
find(
N);
550 if (It == Dependents.
end())
552 for (
const Node *Dependent : It->second) {
553 assert(DependencyCount[Dependent] &&
"Dependency already satisfied");
554 if (--DependencyCount[Dependent] == 0)
555 Ready.emplace(Dependent->ModuleOrder, Dependent);
559 if (Order.
size() !=
SCC.size())
567 NVPTX_MC::verifyInstructionPredicates(
MI->getOpcode(),
568 getSubtargetInfo().getFeatureBits());
571 lowerToMCInst(
MI, Inst);
572 EmitToStreamer(*OutStreamer, Inst);
575void NVPTXAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
577 for (
const auto MO :
MI->operands())
581MCOperand NVPTXAsmPrinter::lowerOperand(
const MachineOperand &MO) {
613 case Type::BFloatTyID:
616 case Type::FloatTyID:
619 case Type::DoubleTyID:
628static NVPTX::VirtualRegisterKind
630 if (RC == &NVPTX::B1RegClass)
632 if (RC == &NVPTX::B16RegClass)
634 if (RC == &NVPTX::B32RegClass)
636 if (RC == &NVPTX::B64RegClass)
638 if (RC == &NVPTX::B128RegClass)
643unsigned NVPTXAsmPrinter::getVirtualRegisterNumber(
Register Reg)
const {
645 assert(It != VRegMapping.
end() &&
"Bad register class");
647 const unsigned Num = It->second.lookup(
Reg);
648 assert(Num &&
"Bad virtual register");
652MCRegister NVPTXAsmPrinter::encodeVirtualRegister(
Register Reg) {
657 const unsigned Num = getVirtualRegisterNumber(
Reg);
658 assert(Num <= NVPTX::VirtualRegisterNumMask &&
659 "Too many virtual registers");
660 return (
static_cast<unsigned>(Kind) << NVPTX::VirtualRegisterKindShift) |
666 assert(
Reg.
id() <= NVPTX::VirtualRegisterNumMask &&
667 "Physical register would decode as a virtual register");
671MCOperand NVPTXAsmPrinter::GetSymbolRef(
const MCSymbol *Symbol) {
677template <
typename OwnerT>
679 bool IsByVal,
bool IsKernel,
StringRef Name,
684 const Align ParamAlign =
687 O <<
".align " << ParamAlign.
value() <<
" .b8 " << Name <<
"["
688 <<
DL.getTypeAllocSize(Ty) <<
"]";
692 assert((Ty->isFloatingPointTy() || Ty->isIntOrPtrTy()) &&
693 "Unknown parameter type");
694 const unsigned Size =
DL.getTypeSizeInBits(Ty).getFixedValue();
701template <
typename OwnerT>
704 Type *RetTy =
Owner->getFunctionType()->getReturnType();
718void NVPTXAsmPrinter::emitCallPrototype(
const CallBase &CB,
719 MCSymbol *PrototypeSymbol)
const {
720 const DataLayout &
DL = getDataLayout();
721 const NVPTXSubtarget &STI = MF->getSubtarget<NVPTXSubtarget>();
723 OutStreamer->emitLabel(PrototypeSymbol);
725 SmallString<128> Str;
726 raw_svector_ostream
O(Str);
728 O <<
".callprototype ";
732 auto MakeArg = [&](
const unsigned I) {
737 printParam(&CB, Ty,
I + AttributeList::FirstArgIndex, IsByVal,
742 const unsigned NumArgs = FTy->getNumParams();
752 if (FTy->isVarArg() && CB.
arg_size() > NumArgs)
753 O << (NonEmptyArgs.empty() ?
"" :
",") <<
" .param .align "
757 if (shouldEmitPTXNoReturn(CB))
761 OutStreamer->emitRawText(
O.str());
764void NVPTXAsmPrinter::emitJumpTable(
const MachineJumpTableEntry &MJT,
765 unsigned MJTI)
const {
766 OutStreamer->emitLabel(GetJTISymbol(MJTI));
768 if (MJT.
MBBs.empty())
773 return MBB->getSymbol();
775 getTargetStreamer()->emitBranchTargetsDirective(Targets);
780bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
781 const MachineBasicBlock &
MBB)
const {
782 const MachineLoopInfo *LI = GetMLI(*MF);
783 assert(LI &&
"NVPTXAsmPrinter requires MachineLoopInfo");
796 if (
const BasicBlock *PBB = PMBB->getBasicBlock()) {
798 PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
801 if (MDNode *UnrollCountMD =
813void NVPTXAsmPrinter::emitBasicBlockStart(
const MachineBasicBlock &
MBB) {
815 if (isLoopHeaderOfNoUnroll(
MBB))
816 getTargetStreamer()->emitPragmaDirective(
"nounroll");
819void NVPTXAsmPrinter::emitFunctionEntryLabel() {
820 SmallString<128> Str;
821 raw_svector_ostream
O(Str);
823 if (!GlobalsEmitted) {
824 emitGlobals(*MF->getFunction().getParent());
825 GlobalsEmitted =
true;
829 MRI = &MF->getRegInfo();
830 F = &MF->getFunction();
831 emitLinkageDirective(
F, O);
839 CurrentFnSym->print(O, MAI);
841 emitFunctionParamList(
F, O);
845 emitKernelFunctionDirectives(*
F, O);
847 if (shouldEmitPTXNoReturn(*
F))
850 OutStreamer->emitRawText(
O.str());
854 OutStreamer->emitRawText(StringRef(
"{\n"));
855 setAndEmitFunctionVirtualRegisters(*MF);
856 encodeDebugInfoRegisterNumbers(*MF);
868 OutStreamer->emitRawText(StringRef(
"}\n"));
872void NVPTXAsmPrinter::emitFunctionBodyStart() {
873 SmallString<128> Str;
874 raw_svector_ostream
O(Str);
875 emitDemotedVars(&MF->getFunction(), O);
876 OutStreamer->emitRawText(
O.str());
878 const auto *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
879 for (
const auto &[CB, Symbol] : MFI->getCallPrototypes())
880 emitCallPrototype(*CB, Symbol);
882 if (
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo())
883 for (
const auto &[Idx, JT] :
enumerate(MJTI->getJumpTables()))
884 emitJumpTable(JT, Idx);
887void NVPTXAsmPrinter::emitFunctionBodyEnd() {
891const MCSymbol *NVPTXAsmPrinter::getFunctionFrameSymbol()
const {
892 return OutContext.getOrCreateSymbol(
DEPOTNAME + Twine(getFunctionNumber()));
895void NVPTXAsmPrinter::emitImplicitDef(
const MachineInstr *
MI)
const {
898 OutStreamer->AddComment(Twine(
"implicit-def: ") +
899 getVirtualRegisterName(RegNo));
901 OutStreamer->AddComment(Twine(
"implicit-def: ") +
903 OutStreamer->addBlankLine();
906void NVPTXAsmPrinter::emitKernelFunctionDirectives(
const Function &
F,
907 raw_ostream &O)
const {
913 O <<
formatv(
".reqntid {0:$[, ]}\n",
918 O <<
formatv(
".maxntid {0:$[, ]}\n",
922 O <<
".minnctapersm " << *Mincta <<
"\n";
925 O <<
".maxnreg " << *Maxnreg <<
"\n";
929 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
930 const NVPTXSubtarget *STI = &NTM.
getSubtarget<NVPTXSubtarget>(
F);
932 if (STI->hasFeature(NVPTX::SM90)) {
938 if (!BlocksAreClusters)
939 O <<
".explicitcluster\n";
941 if (ClusterDim[0] != 0) {
943 "cluster_dim_x != 0 implies cluster_dim_y and cluster_dim_z "
944 "should be non-zero as well");
946 O <<
formatv(
".reqnctapercluster {0:$[, ]}\n",
950 "cluster_dim_x == 0 implies cluster_dim_y and cluster_dim_z "
951 "should be 0 as well");
955 if (BlocksAreClusters) {
956 LLVMContext &Ctx =
F.getContext();
958 Ctx.
diagnose(DiagnosticInfoUnsupported(
959 F,
"blocksareclusters requires reqntid and cluster_dim attributes",
961 else if (!STI->hasFeature(NVPTX::PTX90))
962 Ctx.
diagnose(DiagnosticInfoUnsupported(
963 F,
"blocksareclusters requires PTX version >= 9.0",
966 O <<
".blocksareclusters\n";
970 O <<
".maxclusterrank " << *Maxclusterrank <<
"\n";
974std::string NVPTXAsmPrinter::getVirtualRegisterName(
Register Reg)
const {
978 raw_string_ostream(Name) << NVPTX::getVirtualRegisterPrefix(Kind)
979 << getVirtualRegisterNumber(
Reg);
983void NVPTXAsmPrinter::emitAliasDeclaration(
const GlobalAlias *GA,
988 "NVPTX aliasee must be a non-kernel function definition");
994 emitDeclarationWithName(
F, getSymbol(GA), O);
997void NVPTXAsmPrinter::emitDeclaration(
const Function *
F, raw_ostream &O) {
998 emitDeclarationWithName(
F, getSymbol(
F), O);
1001void NVPTXAsmPrinter::emitDeclarationWithName(
const Function *
F, MCSymbol *S,
1003 emitLinkageDirective(
F, O);
1012 emitFunctionParamList(
F, O);
1014 if (shouldEmitPTXNoReturn(*
F))
1024 return GV->
getName() !=
"llvm.used";
1026 for (
const User *U :
C->users())
1036 if (OtherGV->getName() ==
"llvm.used")
1040 if (
const Function *CurFunc =
I->getFunction()) {
1041 if (OneFunc && (CurFunc != OneFunc))
1082 for (
const User *U :
C->users()) {
1087 if (
const Function *Caller =
I->getFunction())
1095void NVPTXAsmPrinter::emitDeclarations(
const Module &M, raw_ostream &O) {
1096 SmallPtrSet<const Function *, 32> SeenSet;
1098 if (
F.getAttributes().hasFnAttr(
"nvptx-libcall-callee")) {
1099 emitDeclaration(&
F, O);
1103 if (
F.isDeclaration()) {
1106 if (
F.getIntrinsicID())
1110 if (
F.isIntrinsic()) {
1111 LLVMContext &Ctx =
F.getContext();
1112 Ctx.
diagnose(DiagnosticInfoUnsupported(
1113 F,
"unknown intrinsic '" +
F.getName() +
1114 "' cannot be lowered by the NVPTX backend"));
1117 emitDeclaration(&
F, O);
1120 for (
const User *U :
F.users()) {
1126 emitDeclaration(&
F, O);
1132 emitDeclaration(&
F, O);
1147 emitDeclaration(&
F, O);
1153 for (
const GlobalAlias &GA :
M.aliases())
1154 emitAliasDeclaration(&GA, O);
1157void NVPTXAsmPrinter::emitStartOfAsmFile(
Module &M) {
1161 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1165 emitHeader(M, *STI);
1169DwarfDebug *NVPTXAsmPrinter::createDwarfDebug() {
1170 return new NVPTXDwarfDebug(
this);
1173bool NVPTXAsmPrinter::doInitialization(
Module &M) {
1174 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1176 if (
M.alias_size() &&
1177 (!STI.hasFeature(NVPTX::PTX63) || !STI.hasFeature(NVPTX::SM30)))
1183 GlobalsEmitted =
false;
1187 for (
const GlobalValue &GV :
M.global_values())
1193void NVPTXAsmPrinter::emitGlobals(
const Module &M) {
1194 SmallString<128> Str2;
1195 raw_svector_ostream OS2(Str2);
1197 emitDeclarations(M, OS2);
1199 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1207 GlobalVariableDependencyGraph DependencyGraph(M);
1208 for (GlobalVariableSCCIterator
I =
1209 GlobalVariableSCCIterator::begin(DependencyGraph.getEntryNode());
1210 !
I.isAtEnd(); ++
I) {
1215 if (!
SCC.front()->GV) {
1216 assert(
SCC.size() == 1 &&
"Synthetic root must be in its own SCC");
1221 return LHS->ModuleOrder <
RHS->ModuleOrder;
1224 const bool IsCyclic =
I.hasCycle();
1225 DenseSet<const GlobalVariableDependencyNode *> ForwardDeclared;
1227 for (
const auto *Node : SCC)
1228 if (isForwardDeclarableGlobal(
Node->GV))
1229 ForwardDeclared.
insert(Node);
1233 IsCyclic ? orderDefinitionsInSCC(SCC, ForwardDeclared)
1236 for (
const auto *Node : SCC) {
1237 if (!ForwardDeclared.
count(Node))
1240 emitPTXGlobalVariableDefinition(
Node->GV, OS2, STI,
1245 for (
const GlobalVariable *GV : OrderedGlobals)
1246 printModuleLevelGV(GV, OS2,
false, STI);
1251 OutStreamer->emitRawText(OS2.str());
1254void NVPTXAsmPrinter::emitGlobalAlias(
const Module &M,
const GlobalAlias &GA) {
1255 getTargetStreamer()->emitAliasDirective(getSymbol(&GA),
1259NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer()
const {
1260 return static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1265 switch(
CU->getEmissionKind()) {
1278void NVPTXAsmPrinter::emitHeader(
Module &M,
const NVPTXSubtarget &STI) {
1279 auto *TS = getTargetStreamer();
1284 TS->emitVersionDirective(PTXVersion);
1286 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1289 TS->emitTargetDirective(STI.
getTargetName(), TexModeIndependent,
1291 TS->emitAddressSizeDirective(
M.getDataLayout().getPointerSizeInBits());
1294bool NVPTXAsmPrinter::doFinalization(
Module &M) {
1297 if (!GlobalsEmitted) {
1299 GlobalsEmitted =
true;
1308 static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1311 TS->closeLastSection();
1313 TS->emitEmptySectionDirective(
".debug_macinfo");
1317 TS->outputDwarfFileDirectives();
1335void NVPTXAsmPrinter::emitLinkageDirective(
const GlobalValue *V,
1337 if (
static_cast<NVPTXTargetMachine &
>(TM).getDrvInterface() == NVPTX::CUDA) {
1338 if (
V->hasExternalLinkage()) {
1341 else if (
V->isDeclaration())
1345 }
else if (
V->hasAppendingLinkage()) {
1347 "' has unsupported appending linkage type");
1348 }
else if (!
V->hasInternalLinkage() && !
V->hasPrivateLinkage()) {
1354void NVPTXAsmPrinter::printModuleLevelGV(
const GlobalVariable *GVar,
1355 raw_ostream &O,
bool ProcessDemoted,
1356 const NVPTXSubtarget &STI) {
1358 if (shouldSkipModuleLevelGlobal(*GVar))
1377 if (OpaqueType == PTXOpaqueType::Texture) {
1378 O <<
".global .texref ";
1379 getSymbol(GVar)->print(O, MAI);
1384 if (OpaqueType == PTXOpaqueType::Surface) {
1385 O <<
".global .surfref ";
1386 getSymbol(GVar)->print(O, MAI);
1395 emitPTXGlobalVariableDefinition(GVar, O, STI,
false);
1400 if (OpaqueType == PTXOpaqueType::Sampler) {
1401 O <<
".global .samplerref ";
1402 getSymbol(GVar)->print(O, MAI);
1404 const Constant *Initializer =
nullptr;
1407 const ConstantInt *CI =
nullptr;
1418 O <<
"addr_mode_" << i <<
" = ";
1424 O <<
"clamp_to_border";
1427 O <<
"clamp_to_edge";
1438 O <<
"filter_mode = ";
1453 O <<
", force_unnormalized_coords = 1";
1473 const Function *DemotedFunc =
nullptr;
1475 O <<
"// " << GVar->
getName() <<
" has been demoted\n";
1476 localDecls[DemotedFunc].push_back(GVar);
1480 emitPTXGlobalVariableDefinition(GVar, O, STI,
true);
1484void NVPTXAsmPrinter::emitPTXGlobalVariableDefinition(
1485 const GlobalVariable *GVar, raw_ostream &O,
const NVPTXSubtarget &STI,
1486 bool EmitInitializer) {
1487 const DataLayout &
DL = getDataLayout();
1494 if (!STI.hasFeature(NVPTX::PTX40) || !STI.hasFeature(NVPTX::SM30))
1496 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1497 O <<
" .attribute(.managed)";
1501 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1503 const Constant *Initializer =
nullptr;
1510 "' is not allowed in addrspace(" +
1518 O <<
" ." << getPTXFundamentalTypeStr(ETy) <<
" ";
1519 getSymbol(GVar)->print(O, MAI);
1521 if (EmitInitializer && Initializer) {
1523 printScalarConstant(Initializer, O);
1534 "type not supported yet");
1536 const uint64_t ElementSize =
DL.getTypeStoreSize(ETy);
1540 getSymbol(GVar)->print(O, MAI);
1542 O <<
"[" << ElementSize <<
"]";
1543 else if (!EmitInitializer)
1548 AggBuffer aggBuffer(ElementSize, *
this);
1549 bufferAggregateConstant(Initializer, &aggBuffer);
1550 if (aggBuffer.numSymbols()) {
1551 const unsigned int ptrSize = MAI.getCodePointerSize();
1552 if (ElementSize % ptrSize || !aggBuffer.allSymbolsAligned(ptrSize)) {
1557 "' requires at least PTX ISA version 7.1");
1559 getSymbol(GVar)->print(O, MAI);
1560 O <<
"[" << ElementSize <<
"]";
1561 if (EmitInitializer) {
1563 aggBuffer.printBytes(O);
1567 O <<
" .u" << ptrSize * 8 <<
" ";
1568 getSymbol(GVar)->print(O, MAI);
1569 O <<
"[" << ElementSize / ptrSize <<
"]";
1570 if (EmitInitializer) {
1572 aggBuffer.printWords(O);
1578 getSymbol(GVar)->print(O, MAI);
1579 O <<
"[" << ElementSize <<
"]";
1580 if (EmitInitializer) {
1582 aggBuffer.printBytes(O);
1588void NVPTXAsmPrinter::AggBuffer::printSymbol(
unsigned nSym, raw_ostream &os) {
1589 const Value *
v = Symbols[nSym];
1590 const Value *v0 = SymbolsBeforeStripping[nSym];
1595 bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
1598 Name->print(os, AP.MAI);
1601 Name->print(os, AP.MAI);
1604 const MCExpr *Expr = AP.lowerConstantForGV(CExpr,
false);
1605 AP.printMCExpr(*Expr, os);
1610void NVPTXAsmPrinter::AggBuffer::printBytes(raw_ostream &os) {
1611 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1616 unsigned int InitializerCount =
Size;
1619 if (numSymbols() == 0)
1620 while (InitializerCount >= 1 && !buffer[InitializerCount - 1])
1623 symbolPosInBuffer.push_back(InitializerCount);
1624 unsigned int nSym = 0;
1625 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1626 for (
unsigned int pos = 0; pos < InitializerCount;) {
1629 if (pos != nextSymbolPos) {
1630 os << (
unsigned int)buffer[pos];
1637 std::string symText;
1638 llvm::raw_string_ostream oss(symText);
1639 printSymbol(nSym, oss);
1640 for (
unsigned i = 0; i < ptrSize; ++i) {
1644 os <<
"(" << symText <<
")";
1647 nextSymbolPos = symbolPosInBuffer[++nSym];
1648 assert(nextSymbolPos >= pos);
1652void NVPTXAsmPrinter::AggBuffer::printWords(raw_ostream &os) {
1653 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1654 symbolPosInBuffer.push_back(
Size);
1655 unsigned int nSym = 0;
1656 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1657 assert(nextSymbolPos % ptrSize == 0);
1658 for (
unsigned int pos = 0; pos <
Size; pos += ptrSize) {
1661 if (pos == nextSymbolPos) {
1662 printSymbol(nSym, os);
1663 nextSymbolPos = symbolPosInBuffer[++nSym];
1664 assert(nextSymbolPos % ptrSize == 0);
1665 assert(nextSymbolPos >= pos + ptrSize);
1666 }
else if (ptrSize == 4)
1673void NVPTXAsmPrinter::emitDemotedVars(
const Function *
F, raw_ostream &O) {
1674 auto It = localDecls.find(
F);
1675 if (It == localDecls.end())
1680 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1683 for (
const GlobalVariable *GV : GVars) {
1684 O <<
"\t// demoted variable\n\t";
1685 printModuleLevelGV(GV, O,
true, STI);
1709 switch (OpaqueType) {
1711 return ".samplerref";
1722void NVPTXAsmPrinter::emitPTXAddressSpace(
unsigned int AddressSpace,
1723 raw_ostream &O)
const {
1731std::string NVPTXAsmPrinter::getPTXFundamentalTypeStr(
Type *Ty)
const {
1733 case Type::IntegerTyID:
1734 case Type::PointerTyID: {
1735 const uint64_t NumBits = getDataLayout().getTypeStoreSizeInBits(Ty);
1736 assert(NumBits <= 64 &&
"type too large");
1739 case Type::BFloatTyID:
1740 case Type::HalfTyID:
1741 case Type::FloatTyID:
1742 case Type::DoubleTyID:
1750void NVPTXAsmPrinter::emitFunctionParamList(
const Function *
F, raw_ostream &O) {
1751 const DataLayout &
DL = getDataLayout();
1752 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
1754 const NVPTXMachineFunctionInfo *MFI =
1755 MF ? MF->getInfo<NVPTXMachineFunctionInfo>() : nullptr;
1763 const auto NonEmptyArgs =
1765 return !Arg.getType()->isEmptyTy();
1768 if (NonEmptyArgs.empty() && !
F->isVarArg()) {
1775 auto MakeParam = [&](
const auto &IndexedArg) {
1776 const auto &[ParamIndex, Arg] = IndexedArg;
1777 Type *Ty = Arg.getType();
1778 MCSymbol *
const ParamSym = TLI->getParamSymbol(OutContext,
F, ParamIndex);
1784 const bool IsByVal = Arg.hasByValAttr();
1790 if (IsKernelFunc && !AsArray) {
1792 if (!OpaqueType.
empty()) {
1797 O << OpaqueType <<
" " << *ParamSym;
1802 const unsigned AS = PTy->getAddressSpace();
1803 O <<
".param .u" <<
DL.getPointerSizeInBits(AS) <<
" .ptr";
1809 O <<
" .align " << Arg.getParamAlign().valueOrOne().value() <<
" "
1815 printParam(
F, IsByVal ? Arg.getParamByValType() : Ty,
1816 Arg.getArgNo() + AttributeList::FirstArgIndex, IsByVal,
1817 IsKernelFunc, ParamSym->
getName(),
DL, O);
1823 O << (NonEmptyArgs.empty() ?
"" :
",\n") <<
"\t.param .align "
1825 << *TLI->getParamSymbol(OutContext,
F, -1) <<
"[]";
1830void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1832 auto *TS = getTargetStreamer();
1837 TS->emitLocalDirective(MFI.
getMaxAlign(), getFunctionFrameSymbol(),
1841 const NVPTXRegisterInfo *NRI =
1845 TS->emitRegDirective(
1846 NRI->getRegSizeInBits(FrameReg, *MRI).getFixedValue(),
1855 Register VR = Register::index2VirtReg(
I);
1858 auto &RCRegMap = VRegMapping[MRI->
getRegClass(VR)];
1859 RCRegMap[VR] = RCRegMap.
size() + 1;
1867 const auto It = VRegMapping.
find(&RC);
1868 if (It == VRegMapping.
end() || It->second.empty())
1871 TS->emitRegDirective(
1872 TRI->getRegSizeInBits(RC).getFixedValue(),
1874 It->second.size() + 1);
1880void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
1882 const NVPTXSubtarget &STI = MF.
getSubtarget<NVPTXSubtarget>();
1892 NRI->addToDebugRegisterMap(
Reg, getVirtualRegisterName(
Reg));
1895void NVPTXAsmPrinter::printFPConstant(
const ConstantFP *Fp,
1896 raw_ostream &O)
const {
1909void NVPTXAsmPrinter::printScalarConstant(
const Constant *CPV, raw_ostream &O) {
1915 const APInt API = CFP->getValueAPF().bitcastToAPInt();
1927 if (EmitGeneric && !
isa<Function>(CPV) && !IsNonGenericPointer) {
1929 getSymbol(GVar)->print(O, MAI);
1932 getSymbol(GVar)->print(O, MAI);
1944void NVPTXAsmPrinter::bufferLEByte(
const Constant *CPV,
int Bytes,
1945 AggBuffer *AggBuffer) {
1946 const DataLayout &
DL = getDataLayout();
1947 int AllocSize =
DL.getTypeAllocSize(CPV->
getType());
1951 AggBuffer->addZeros(Bytes ? Bytes : AllocSize);
1956 auto AddIntToBuffer = [AggBuffer, Bytes](
const APInt &Val) {
1957 size_t NumBytes = (Val.getBitWidth() + 7) / 8;
1963 for (
unsigned I = 0;
I < NumBytes - 1; ++
I) {
1964 Buf[
I] = Val.extractBitsAsZExtValue(8,
I * 8);
1966 size_t LastBytePosition = (NumBytes - 1) * 8;
1967 size_t LastByteBits = Val.getBitWidth() - LastBytePosition;
1969 Val.extractBitsAsZExtValue(LastByteBits, LastBytePosition);
1970 AggBuffer->addBytes(Buf.data(), NumBytes, Bytes);
1974 case Type::IntegerTyID:
1980 if (
const auto *CI =
1985 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1986 Value *
V = Cexpr->getOperand(0)->stripPointerCasts();
1987 AggBuffer->addSymbol(V, Cexpr->getOperand(0));
1988 AggBuffer->addZeros(AllocSize);
1995 AggBuffer->addSymbol(Cexpr, Cexpr);
1996 AggBuffer->addZeros(AllocSize);
2002 case Type::HalfTyID:
2003 case Type::BFloatTyID:
2004 case Type::FloatTyID:
2005 case Type::DoubleTyID:
2006 case Type::FP128TyID:
2010 case Type::PointerTyID: {
2012 AggBuffer->addSymbol(GVar, GVar);
2014 const Value *
v = Cexpr->stripPointerCasts();
2015 AggBuffer->addSymbol(v, Cexpr);
2017 AggBuffer->addZeros(AllocSize);
2021 case Type::ArrayTyID:
2022 case Type::FixedVectorTyID:
2023 case Type::StructTyID: {
2027 unsigned StartPos = AggBuffer->getCurpos();
2028 bufferAggregateConstant(CPV, AggBuffer);
2029 unsigned Written = AggBuffer->getCurpos() - StartPos;
2030 unsigned SlotSize = std::max<int>(Bytes, AllocSize);
2031 if (SlotSize > Written)
2032 AggBuffer->addZeros(SlotSize - Written);
2034 AggBuffer->addZeros(Bytes);
2045void NVPTXAsmPrinter::bufferAggregateConstant(
const Constant *CPV,
2046 AggBuffer *aggBuffer) {
2047 const DataLayout &
DL = getDataLayout();
2049 auto ExtendBuffer = [](APInt Val, AggBuffer *Buffer) {
2052 unsigned NumBits = std::min(8u, Val.
getBitWidth() -
I * 8);
2060 for (
unsigned I :
llvm::seq(VTy->getNumElements()))
2069 ExtendBuffer(CI->
getValue(), aggBuffer);
2075 assert(CFP->getType()->isFloatingPointTy() &&
"Expected fp constant!");
2076 if (CFP->getType()->isFP128Ty()) {
2077 ExtendBuffer(CFP->getValueAPF().bitcastToAPInt(), aggBuffer);
2091 bufferAggregateConstVec(CVec, aggBuffer);
2096 for (
unsigned I :
llvm::seq(CDS->getNumElements()))
2097 bufferLEByte(
cast<Constant>(CDS->getElementAsConstant(
I)), 0, aggBuffer);
2106 ?
DL.getStructLayout(ST)->getElementOffset(0) +
2107 DL.getTypeAllocSize(ST)
2108 :
DL.getStructLayout(ST)->getElementOffset(
I + 1);
2109 int Bytes = EndOffset -
DL.getStructLayout(ST)->getElementOffset(
I);
2118void NVPTXAsmPrinter::bufferAggregateConstVec(
const ConstantVector *CV,
2119 AggBuffer *aggBuffer) {
2121 const unsigned BuffSize = aggBuffer->getBufferSize();
2124 if (BuffSize >= NumElems) {
2137 assert(ElemTySize < 8 &&
"Expected sub-byte data type.");
2138 assert(8 % ElemTySize == 0 &&
"Element type size must evenly divide a byte.");
2140 unsigned NumElemsPerByte = 8 / ElemTySize;
2141 unsigned NumCompleteBytes = NumElems / NumElemsPerByte;
2142 unsigned NumTailElems = NumElems % NumElemsPerByte;
2147 auto ConvertSubCVtoInt8 = [
this, &ElemTy](
const ConstantVector *CV,
2148 unsigned Start,
unsigned End,
2149 unsigned NumPaddingZeros = 0) {
2156 if (NumPaddingZeros)
2157 SubCVElems.
append(NumPaddingZeros, ConstantInt::getNullValue(ElemTy));
2163 ConstantInt *MergedElem =
2170 "Cannot lower vector global with unusual element type");
2177 for (
unsigned ByteIdx :
llvm::seq(NumCompleteBytes))
2178 bufferLEByte(ConvertSubCVtoInt8(CV, ByteIdx * NumElemsPerByte,
2179 (ByteIdx + 1) * NumElemsPerByte),
2183 if (NumTailElems > 0)
2184 bufferLEByte(ConvertSubCVtoInt8(CV, NumElems - NumTailElems, NumElems,
2185 NumElemsPerByte - NumTailElems),
2194NVPTXAsmPrinter::lowerConstantForGV(
const Constant *CV,
2195 bool ProcessingGeneric)
const {
2196 MCContext &Ctx = OutContext;
2206 if (ProcessingGeneric)
2216 switch (
CE->getOpcode()) {
2220 case Instruction::AddrSpaceCast: {
2223 if (DstTy->getAddressSpace() == 0)
2229 case Instruction::GetElementPtr: {
2230 const DataLayout &
DL = getDataLayout();
2233 APInt OffsetAI(
DL.getPointerTypeSizeInBits(
CE->getType()), 0);
2236 const MCExpr *
Base = lowerConstantForGV(
CE->getOperand(0),
2241 int64_t
Offset = OffsetAI.getSExtValue();
2246 case Instruction::Trunc:
2252 case Instruction::BitCast:
2253 return lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2255 case Instruction::IntToPtr: {
2256 const DataLayout &
DL = getDataLayout();
2264 return lowerConstantForGV(
Op, ProcessingGeneric);
2269 case Instruction::PtrToInt: {
2270 const DataLayout &
DL = getDataLayout();
2275 Type *Ty =
CE->getType();
2277 const MCExpr *OpExpr = lowerConstantForGV(
Op, ProcessingGeneric);
2281 if (
DL.getTypeAllocSize(Ty) ==
DL.getTypeAllocSize(
Op->getType()))
2287 unsigned InBits =
DL.getTypeAllocSizeInBits(
Op->getType());
2294 case Instruction::Add: {
2295 const MCExpr *
LHS = lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2296 const MCExpr *
RHS = lowerConstantForGV(
CE->getOperand(1), ProcessingGeneric);
2297 switch (
CE->getOpcode()) {
2309 return lowerConstantForGV(
C, ProcessingGeneric);
2313 raw_string_ostream OS(S);
2314 OS <<
"Unsupported expression in static initializer: ";
2315 CE->printAsOperand(OS,
false,
2320void NVPTXAsmPrinter::printMCExpr(
const MCExpr &Expr, raw_ostream &OS)
const {
2321 OutContext.getAsmInfo().printExpr(OS, Expr);
2326bool NVPTXAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
2327 const char *ExtraCode, raw_ostream &O) {
2328 if (ExtraCode && ExtraCode[0]) {
2329 if (ExtraCode[1] != 0)
2332 switch (ExtraCode[0]) {
2346bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
2348 const char *ExtraCode,
2350 if (ExtraCode && ExtraCode[0])
2360void NVPTXAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
2362 const MachineOperand &MO =
MI->getOperand(OpNum);
2366 if (MO.
getReg() == NVPTX::VRDepot)
2367 getFunctionFrameSymbol()->print(O, MAI);
2371 O << getVirtualRegisterName(MO.
getReg());
2384 PrintSymbolOperand(MO, O);
2400void NVPTXAsmPrinter::printMemOperand(
const MachineInstr *
MI,
unsigned OpNum,
2401 raw_ostream &O,
const char *Modifier) {
2404 if (Modifier && strcmp(Modifier,
"add") == 0) {
2408 if (
MI->getOperand(OpNum + 1).isImm() &&
2409 MI->getOperand(OpNum + 1).getImm() == 0)
2420 return !Trimmed.
empty() &&
2421 (std::isalpha(
static_cast<unsigned char>(Trimmed[0])) ||
2428 if (!
MI || !
MI->getDebugLoc())
2430 const DISubprogram *SP =
MI->getMF()->getFunction().getSubprogram();
2434 if (!
DL->getFile() || !
DL->getLine() ||
DL->isImplicitCode())
2440struct InlineAsmInliningContext {
2442 unsigned FileIA = 0;
2443 unsigned LineIA = 0;
2446 bool hasInlinedAt()
const {
return FuncNameSym !=
nullptr; }
2452static InlineAsmInliningContext
2456 InlineAsmInliningContext Ctx;
2458 if (!InlinedAt || !InlinedAt->getFile() || !NVDD ||
2465 Ctx.FileIA =
Streamer.emitDwarfFileDirective(
2466 0, InlinedAt->getFile()->getDirectory(),
2467 InlinedAt->getFile()->getFilename(), std::nullopt, std::nullopt, CUID);
2468 Ctx.LineIA = InlinedAt->getLine();
2469 Ctx.ColIA = InlinedAt->getColumn();
2473void NVPTXAsmPrinter::emitInlineAsm(StringRef Str,
const MCSubtargetInfo &STI,
2474 const MCTargetOptions &MCOptions,
2475 const MDNode *LocMDNode,
2477 const MachineInstr *
MI) {
2478 assert(!Str.empty() &&
"Can't emit empty inline asm block");
2479 if (Str.back() == 0)
2480 Str = Str.substr(0, Str.size() - 1);
2482 auto emitAsmStr = [&](StringRef AsmStr) {
2483 emitInlineAsmStart();
2484 OutStreamer->emitRawText(AsmStr);
2485 emitInlineAsmEnd(STI,
nullptr,
MI);
2494 const DIFile *
File =
DL->getFile();
2495 unsigned Line =
DL->getLine();
2496 const unsigned Column =
DL->getColumn();
2497 const unsigned CUID = OutStreamer->getContext().getDwarfCompileUnitID();
2498 const unsigned FileNumber = OutStreamer->emitDwarfFileDirective(
2499 0,
File->getDirectory(),
File->getFilename(), std::nullopt, std::nullopt,
2502 auto *NVDD =
static_cast<NVPTXDwarfDebug *
>(getDwarfDebug());
2503 InlineAsmInliningContext InlineCtx =
2506 SmallVector<StringRef, 16>
Lines;
2507 Str.split(Lines,
'\n');
2508 emitInlineAsmStart();
2509 for (
const StringRef &L : Lines) {
2510 StringRef RTrimmed =
L.rtrim(
'\r');
2512 if (InlineCtx.hasInlinedAt()) {
2513 OutStreamer->emitDwarfLocDirectiveWithInlinedAt(
2514 FileNumber, Line, Column, InlineCtx.FileIA, InlineCtx.LineIA,
2516 File->getFilename());
2518 OutStreamer->emitDwarfLocDirective(FileNumber, Line, Column,
2520 File->getFilename());
2523 OutStreamer->emitRawText(RTrimmed);
2526 emitInlineAsmEnd(STI,
nullptr,
MI);
2529char NVPTXAsmPrinter::ID = 0;
2536LLVMInitializeNVPTXAsmPrinter() {
2557 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 ManagedStatic< DebugCounterOwner > Owner
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 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 bool canDemoteGlobalVar(const GlobalVariable *GV, Function const *&f)
static void printReturnValClause(const OwnerT *Owner, StringRef Name, const DataLayout &DL, raw_ostream &O)
static StringRef getPTXAddressSpaceName(unsigned AddressSpace)
The PTX state space directive for AddressSpace, or an empty string if it does not name one,...
static StringRef getPTXOpaqueTypeName(PTXOpaqueType OpaqueType)
The PTX opaque type directive for an image or sampler handle, or an empty string for PTXOpaqueType::N...
static bool useFuncSeen(const Constant *C, const SmallPtrSetImpl< const Function * > &SeenSet)
static NVPTX::VirtualRegisterKind getVirtualRegisterKind(const TargetRegisterClass *RC)
static void printParam(const OwnerT *Owner, Type *Ty, unsigned AttrIdx, bool IsByVal, bool IsKernel, StringRef Name, const DataLayout &DL, raw_ostream &O)
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.
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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...
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
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.
A parsed version of the target data layout string in and methods for querying it.
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
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...
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.
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.
StringRef getName() const
getName - Get the symbol name.
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 alignment of this function's frame.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ 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(const MCSymbol *Symbol) const
Check whether Symbol's handle was replaced with an image reference.
void clearDebugRegisterMap() const
Register getFrameLocalRegister(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
unsigned getMaxRequiredAlignment() const
StringRef getTargetName() 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.
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isFP128Ty() const
Return true if this is 'fp128'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isAggregateType() const
Return true if the type is an aggregate type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
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 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.
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 &)
unsigned promoteScalarKernelArgumentSize(unsigned Size)
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)
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...
unsigned promoteScalarArgumentSize(unsigned Size)
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
This struct is a compact representation of a valid (non-zero power of two) alignment.
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,...