LLVM 24.0.0git
NVPTXAsmPrinter.cpp
Go to the documentation of this file.
1//===-- NVPTXAsmPrinter.cpp - NVPTX LLVM assembly writer ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to NVPTX assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "NVPTXAsmPrinter.h"
19#include "NVPTX.h"
20#include "NVPTXDwarfDebug.h"
21#include "NVPTXMCExpr.h"
23#include "NVPTXRegisterInfo.h"
24#include "NVPTXSubtarget.h"
25#include "NVPTXTargetMachine.h"
26#include "NVPTXUtilities.h"
27#include "NVVMProperties.h"
29#include "cl_common_defines.h"
30#include "llvm/ADT/APFloat.h"
31#include "llvm/ADT/APInt.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/DenseSet.h"
36#include "llvm/ADT/STLExtras.h"
37#include "llvm/ADT/Sequence.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/Twine.h"
59#include "llvm/IR/Argument.h"
60#include "llvm/IR/Attributes.h"
61#include "llvm/IR/BasicBlock.h"
62#include "llvm/IR/Constant.h"
63#include "llvm/IR/Constants.h"
64#include "llvm/IR/DataLayout.h"
65#include "llvm/IR/DebugInfo.h"
67#include "llvm/IR/DebugLoc.h"
69#include "llvm/IR/Function.h"
70#include "llvm/IR/GlobalAlias.h"
71#include "llvm/IR/GlobalValue.h"
73#include "llvm/IR/Instruction.h"
74#include "llvm/IR/LLVMContext.h"
75#include "llvm/IR/Module.h"
76#include "llvm/IR/Operator.h"
77#include "llvm/IR/Type.h"
78#include "llvm/IR/User.h"
79#include "llvm/MC/MCExpr.h"
80#include "llvm/MC/MCInst.h"
81#include "llvm/MC/MCInstrDesc.h"
82#include "llvm/MC/MCStreamer.h"
83#include "llvm/MC/MCSymbol.h"
88#include "llvm/Support/Endian.h"
95#include <algorithm>
96#include <cassert>
97#include <cstdint>
98#include <cstring>
99#include <map>
100#include <set>
101#include <string>
102
103using namespace llvm;
104
105#define DEPOTNAME "__local_depot"
106
108 assert(V.hasName() && "Found texture variable with no name");
109 return V.getName();
110}
111
113 assert(V.hasName() && "Found surface variable with no name");
114 return V.getName();
115}
116
118 assert(V.hasName() && "Found sampler variable with no name");
119 return V.getName();
120}
121
122/// Emits initial debug location directive.
124 DwarfDebug *DD,
125 MCStreamer &OutStreamer) {
126 if (!DD)
127 return;
128
129 assert(OutStreamer.hasRawTextSupport() && "Expected assembly output mode.");
130 // This is NVPTX specific and it's unclear why.
131 // PR51079: If we have code without debug information we need to give up.
132 const DISubprogram *SP = MF.getFunction().getSubprogram();
133 if (!SP)
134 return;
135 assert(SP->getUnit());
136 // NoDebug and DebugDirectivesOnly do not require emitting the initial loc
137 // directive. NoDebug does not require any debug directives and the initial
138 // loc directive is not needed for DebugDirectivesOnly as it is redundant
139 // assuming this is a non-empty function.
140 if (SP->getUnit()->isDebugDirectivesOnly() || SP->getUnit()->isNoDebug())
141 return;
142
143 (void)DD->emitInitialLocDirective(MF, /*CUID=*/0);
144}
145
146namespace {
147
148/// Return a list of GlobalVariables on which \p V depends.
149static void
150discoverDependentGlobals(const Value *V,
153 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
154 if (Seen.insert(GV).second)
155 Globals.push_back(GV);
156 return;
157 }
158
159 // Global values are emitted as symbols. Their operands do not contribute to
160 // the initializer expression that refers to that symbol.
161 if (isa<GlobalValue>(V))
162 return;
163
164 // lowerConstantForGV emits a GEP as its base symbol plus a constant byte
165 // offset. Symbols used to compute an index are not part of that expression.
166 if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
167 discoverDependentGlobals(GEP->getPointerOperand(), Globals, Seen);
168 return;
169 }
170
171 if (const User *U = dyn_cast<User>(V))
172 for (const auto &O : U->operands())
173 discoverDependentGlobals(O, Globals, Seen);
174}
175
176struct GlobalVariableDependencyNode {
177 const GlobalVariable *GV = nullptr;
178 unsigned ModuleOrder = 0;
180};
181
182class GlobalVariableDependencyGraph {
183 // scc_iterator needs a single entry node. Global initializer dependencies
184 // may be disconnected, so use a synthetic root with an edge to every global.
185 GlobalVariableDependencyNode SyntheticRoot;
186 // Edges store pointers into Nodes, so node addresses must remain stable while
187 // the graph is constructed.
188 std::map<const GlobalVariable *, GlobalVariableDependencyNode> Nodes;
189
190public:
191 explicit GlobalVariableDependencyGraph(const Module &M) {
192 unsigned ModuleOrder = 0;
193 for (const GlobalVariable &GV : M.globals()) {
194 GlobalVariableDependencyNode &Node = Nodes.try_emplace(&GV).first->second;
195 Node.GV = &GV;
196 Node.ModuleOrder = ModuleOrder++;
197 SyntheticRoot.Dependencies.push_back(&Node);
198 }
199
200 for (auto &[GV, Node] : Nodes) {
202 SmallPtrSet<const GlobalVariable *, 4> Seen;
203 for (const Use &Operand : GV->operands())
204 discoverDependentGlobals(Operand, Dependencies, Seen);
205
206 for (const GlobalVariable *Dependency : Dependencies) {
207 auto It = Nodes.find(Dependency);
208 if (It != Nodes.end())
209 Node.Dependencies.push_back(&It->second);
210 }
211 }
212 }
213
214 const GlobalVariableDependencyNode *getEntryNode() const {
215 return &SyntheticRoot;
216 }
217};
218
219struct GlobalVariableDependencyGraphTraits {
220 using NodeRef = const GlobalVariableDependencyNode *;
221 using ChildIteratorType =
223
224 static NodeRef getEntryNode(NodeRef Node) { return Node; }
225 static ChildIteratorType child_begin(NodeRef Node) {
226 return Node->Dependencies.begin();
227 }
228 static ChildIteratorType child_end(NodeRef Node) {
229 return Node->Dependencies.end();
230 }
231};
232
233using GlobalVariableSCCIterator =
234 scc_iterator<const GlobalVariableDependencyNode *,
235 GlobalVariableDependencyGraphTraits>;
236
237static bool shouldSkipModuleLevelGlobal(const GlobalVariable &GV) {
238 if (GV.hasSection() && GV.getSection() == "llvm.metadata")
239 return true;
240 return GV.getName().starts_with("llvm.") || GV.getName().starts_with("nvvm.");
241}
242
243static bool isForwardDeclarableGlobal(const GlobalVariable *GVar) {
244 if (shouldSkipModuleLevelGlobal(*GVar) || GVar->isDeclaration() ||
246 return false;
247
248 // A PTX .extern declaration can be resolved by a later .visible, .weak, or
249 // .common definition, but not by a static definition.
250 if (GVar->hasExternalLinkage())
251 return GVar->hasInitializer();
252
253 if (GVar->hasLinkOnceLinkage() || GVar->hasWeakLinkage() ||
255 return true;
256
257 return false;
258}
259
260/// Order definitions after treating references to forward-declared globals as
261/// already satisfied. A remaining cycle cannot be emitted portably because it
262/// requires an undeclared forward reference.
263static SmallVector<const GlobalVariable *, 4> orderDefinitionsInSCC(
265 const DenseSet<const GlobalVariableDependencyNode *> &ForwardDeclared) {
266 using Node = GlobalVariableDependencyNode;
267
269 SCCSet.insert_range(SCC);
270
271 DenseMap<const Node *, unsigned> DependencyCount;
273 std::set<std::pair<unsigned, const Node *>> Ready;
274
275 // Dependencies outside this SCC have already been emitted. Forward-declared
276 // dependencies are also satisfied, so only count the remaining SCC edges.
277 for (const Node *N : SCC) {
278 unsigned &Count = DependencyCount[N];
279 for (const Node *Dependency : N->Dependencies) {
280 if (!SCCSet.count(Dependency) || ForwardDeclared.count(Dependency))
281 continue;
282 ++Count;
283 Dependents[Dependency].push_back(N);
284 }
285 if (Count == 0)
286 Ready.emplace(N->ModuleOrder, N);
287 }
288
290 while (!Ready.empty()) {
291 const Node *N = Ready.begin()->second;
292 Ready.erase(Ready.begin());
293 Order.push_back(N->GV);
294
295 auto It = Dependents.find(N);
296 if (It == Dependents.end())
297 continue;
298 for (const Node *Dependent : It->second) {
299 assert(DependencyCount[Dependent] && "Dependency already satisfied");
300 if (--DependencyCount[Dependent] == 0)
301 Ready.emplace(Dependent->ModuleOrder, Dependent);
302 }
303 }
304
305 if (Order.size() != SCC.size())
306 report_fatal_error("Circular dependency found in global variable set");
307 return Order;
308}
309
310} // namespace
311
312void NVPTXAsmPrinter::emitInstruction(const MachineInstr *MI) {
313 NVPTX_MC::verifyInstructionPredicates(MI->getOpcode(),
314 getSubtargetInfo().getFeatureBits());
315
316 MCInst Inst;
317 lowerToMCInst(MI, Inst);
319}
320
321void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
322 OutMI.setOpcode(MI->getOpcode());
323 for (const auto MO : MI->operands())
324 OutMI.addOperand(lowerOperand(MO));
325}
326
327MCOperand NVPTXAsmPrinter::lowerOperand(const MachineOperand &MO) {
328 switch (MO.getType()) {
329 default:
330 llvm_unreachable("unknown operand type");
332 return MCOperand::createReg(encodeVirtualRegister(MO.getReg()));
334 return MCOperand::createImm(MO.getImm());
339 return GetSymbolRef(GetExternalSymbolSymbol(MO.getSymbolName()));
341 // The jump table index names the .branchtargets list emitted for a brx.idx
342 // (see emitFunctionBodyStart); reference it by that label.
343 return GetSymbolRef(
344 OutContext.getOrCreateSymbol("$L_brx_" + Twine(MO.getIndex())));
346 return GetSymbolRef(getSymbol(MO.getGlobal()));
348 const ConstantFP *Cnt = MO.getFPImm();
349 const APFloat &Val = Cnt->getValueAPF();
350
351 switch (Cnt->getType()->getTypeID()) {
352 default:
353 report_fatal_error("Unsupported FP type");
354 break;
355 case Type::HalfTyID:
358 case Type::BFloatTyID:
361 case Type::FloatTyID:
364 case Type::DoubleTyID:
367 }
368 break;
369 }
370 }
371}
372
373unsigned NVPTXAsmPrinter::encodeVirtualRegister(unsigned Reg) {
375 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
376
377 DenseMap<unsigned, unsigned> &RegMap = VRegMapping[RC];
378 unsigned RegNum = RegMap[Reg];
379
380 // Encode the register class in the upper 4 bits
381 // Must be kept in sync with NVPTXInstPrinter::printRegName
382 unsigned Ret = 0;
383 if (RC == &NVPTX::B1RegClass) {
384 Ret = (1 << 28);
385 } else if (RC == &NVPTX::B16RegClass) {
386 Ret = (2 << 28);
387 } else if (RC == &NVPTX::B32RegClass) {
388 Ret = (3 << 28);
389 } else if (RC == &NVPTX::B64RegClass) {
390 Ret = (4 << 28);
391 } else if (RC == &NVPTX::B128RegClass) {
392 Ret = (7 << 28);
393 } else {
394 report_fatal_error("Bad register class");
395 }
396
397 // Insert the vreg number
398 Ret |= (RegNum & 0x0FFFFFFF);
399 return Ret;
400 } else {
401 // Some special-use registers are actually physical registers.
402 // Encode this as the register class ID of 0 and the real register ID.
403 return Reg & 0x0FFFFFFF;
404 }
405}
406
407MCOperand NVPTXAsmPrinter::GetSymbolRef(const MCSymbol *Symbol) {
408 const MCExpr *Expr;
409 Expr = MCSymbolRefExpr::create(Symbol, OutContext);
410 return MCOperand::createExpr(Expr);
411}
412
413void NVPTXAsmPrinter::printReturnValStr(const Function *F, raw_ostream &O) {
414 const DataLayout &DL = getDataLayout();
415 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
416 const auto *TLI = cast<NVPTXTargetLowering>(STI.getTargetLowering());
417
418 Type *Ty = F->getReturnType();
419 // A void or zero-sized return type (e.g. an empty struct) produces no return
420 // parameter.
421 if (Ty->isVoidTy() || Ty->isEmptyTy())
422 return;
423 O << " (";
424
425 auto PrintScalarRetVal = [&](unsigned Size) {
426 O << ".param .b" << promoteScalarArgumentSize(Size) << " func_retval0";
427 };
428 if (shouldPassAsArray(Ty)) {
429 const unsigned TotalSize = DL.getTypeAllocSize(Ty);
430 const Align RetAlignment =
431 getPTXParamAlign(F, Ty, AttributeList::ReturnIndex, DL);
432 O << ".param .align " << RetAlignment.value() << " .b8 func_retval0["
433 << TotalSize << "]";
434 } else if (Ty->isFloatingPointTy()) {
435 PrintScalarRetVal(Ty->getPrimitiveSizeInBits());
436 } else if (auto *ITy = dyn_cast<IntegerType>(Ty)) {
437 PrintScalarRetVal(ITy->getBitWidth());
438 } else if (isa<PointerType>(Ty)) {
439 PrintScalarRetVal(TLI->getPointerTy(DL).getSizeInBits());
440 } else
441 llvm_unreachable("Unknown return type");
442 O << ") ";
443}
444
445void NVPTXAsmPrinter::printReturnValStr(const MachineFunction &MF,
446 raw_ostream &O) {
447 const Function &F = MF.getFunction();
448 printReturnValStr(&F, O);
449}
450
451void NVPTXAsmPrinter::emitCallPrototype(const CallBase &CB,
452 unsigned UniqueCallSite,
453 raw_ostream &O) const {
454 const DataLayout &DL = getDataLayout();
455 const NVPTXSubtarget &STI = MF->getSubtarget<NVPTXSubtarget>();
456 const auto *TLI = cast<NVPTXTargetLowering>(STI.getTargetLowering());
457 const auto PtrVT = TLI->getPointerTy(DL);
458 Type *RetTy = CB.getFunctionType()->getReturnType();
459
460 O << "prototype_" << UniqueCallSite << " : .callprototype ";
461
462 if (RetTy->isVoidTy() || RetTy->isEmptyTy()) {
463 O << "()";
464 } else {
465 O << "(";
466 if (shouldPassAsArray(RetTy)) {
467 const Align RetAlign =
468 getPTXParamAlign(&CB, RetTy, AttributeList::ReturnIndex, DL);
469 O << ".param .align " << RetAlign.value() << " .b8 _["
470 << DL.getTypeAllocSize(RetTy) << "]";
471 } else if (RetTy->isFloatingPointTy() || RetTy->isIntegerTy()) {
472 unsigned size = 0;
473 if (auto *ITy = dyn_cast<IntegerType>(RetTy)) {
474 size = ITy->getBitWidth();
475 } else {
476 assert(RetTy->isFloatingPointTy() &&
477 "Floating point type expected here");
478 size = RetTy->getPrimitiveSizeInBits();
479 }
480 // PTX ABI requires all scalar return values to be at least 32
481 // bits in size. fp16 normally uses .b16 as its storage type in
482 // PTX, so its size must be adjusted here, too.
484
485 O << ".param .b" << size << " _";
486 } else if (isa<PointerType>(RetTy)) {
487 O << ".param .b" << PtrVT.getSizeInBits() << " _";
488 } else {
489 llvm_unreachable("Unknown return type");
490 }
491 O << ") ";
492 }
493 O << "_ (";
494
495 auto MakeArg = [&](const unsigned I) {
496 Type *Ty = CB.getArgOperand(I)->getType();
497
498 if (CB.paramHasAttr(I, Attribute::ByVal)) {
499 Type *ETy = CB.getParamByValType(I);
500 Align ParamByValAlign = getDeviceByValParamAlign(
501 &CB, ETy, I + AttributeList::FirstArgIndex, DL);
502
503 O << ".param .align " << ParamByValAlign.value() << " .b8 _["
504 << DL.getTypeAllocSize(ETy) << "]";
505 return;
506 }
507
508 if (shouldPassAsArray(Ty)) {
509 Align ParamAlign =
510 getPTXParamAlign(&CB, Ty, I + AttributeList::FirstArgIndex, DL);
511 O << ".param .align " << ParamAlign.value() << " .b8 _["
512 << DL.getTypeAllocSize(Ty) << "]";
513 return;
514 }
515 // scalar type
516 unsigned sz = 0;
517 if (auto *ITy = dyn_cast<IntegerType>(Ty)) {
518 sz = promoteScalarArgumentSize(ITy->getBitWidth());
519 } else if (isa<PointerType>(Ty)) {
520 sz = PtrVT.getSizeInBits();
521 } else {
522 sz = Ty->getPrimitiveSizeInBits();
523 }
524 O << ".param .b" << sz << " _";
525 };
526
527 const FunctionType *FTy = CB.getFunctionType();
528 const unsigned NumArgs = FTy->getNumParams();
529
530 // Zero-sized arguments (e.g. empty structs) are not passed and so do not
531 // appear in the prototype.
532 const auto NonEmptyArgs = make_filter_range(seq(NumArgs), [&](unsigned I) {
533 return !CB.getArgOperand(I)->getType()->isEmptyTy();
534 });
535
536 interleave(NonEmptyArgs, O, MakeArg, ", ");
537
538 if (FTy->isVarArg() && CB.arg_size() > NumArgs)
539 O << (NonEmptyArgs.empty() ? "" : ",") << " .param .align "
540 << STI.getMaxRequiredAlignment() << " .b8 _[]";
541
542 O << ")";
543 if (shouldEmitPTXNoReturn(&CB, TM))
544 O << " .noreturn";
545 O << ";\n";
546}
547
548void NVPTXAsmPrinter::emitJumpTable(const MachineJumpTableEntry &MJT,
549 unsigned MJTI, raw_ostream &O) const {
550 O << "$L_brx_" << MJTI << ":\n";
551
552 if (MJT.MBBs.empty())
553 return;
554
555 O << "\t.branchtargets\n\t\t";
557 MJT.MBBs, O,
558 [&](const MachineBasicBlock *MBB) { MBB->getSymbol()->print(O, MAI); },
559 ",\n\t\t");
560 O << ";\n";
561}
562
563// Return true if MBB is the header of a loop marked with
564// llvm.loop.unroll.disable or llvm.loop.unroll.count=1.
565bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
566 const MachineBasicBlock &MBB) const {
567 MachineLoopInfo &LI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
568 // We insert .pragma "nounroll" only to the loop header.
569 if (!LI.isLoopHeader(&MBB))
570 return false;
571
572 // llvm.loop.unroll.disable is marked on the back edges of a loop. Therefore,
573 // we iterate through each back edge of the loop with header MBB, and check
574 // whether its metadata contains llvm.loop.unroll.disable.
575 for (const MachineBasicBlock *PMBB : MBB.predecessors()) {
576 if (LI.getLoopFor(PMBB) != LI.getLoopFor(&MBB)) {
577 // Edges from other loops to MBB are not back edges.
578 continue;
579 }
580 if (const BasicBlock *PBB = PMBB->getBasicBlock()) {
581 if (MDNode *LoopID =
582 PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
583 if (GetUnrollMetadata(LoopID, "llvm.loop.unroll.disable"))
584 return true;
585 if (MDNode *UnrollCountMD =
586 GetUnrollMetadata(LoopID, "llvm.loop.unroll.count")) {
587 if (mdconst::extract<ConstantInt>(UnrollCountMD->getOperand(1))
588 ->isOne())
589 return true;
590 }
591 }
592 }
593 }
594 return false;
595}
596
597void NVPTXAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
599 if (isLoopHeaderOfNoUnroll(MBB))
600 OutStreamer->emitRawText(StringRef("\t.pragma \"nounroll\";\n"));
601}
602
604 SmallString<128> Str;
605 raw_svector_ostream O(Str);
606
607 if (!GlobalsEmitted) {
608 emitGlobals(*MF->getFunction().getParent());
609 GlobalsEmitted = true;
610 }
611
612 // Set up
613 MRI = &MF->getRegInfo();
614 F = &MF->getFunction();
615 emitLinkageDirective(F, O);
616 if (isKernelFunction(*F))
617 O << ".entry ";
618 else {
619 O << ".func ";
620 printReturnValStr(*MF, O);
621 }
622
623 CurrentFnSym->print(O, MAI);
624
625 emitFunctionParamList(F, O);
626 O << "\n";
627
628 if (isKernelFunction(*F))
629 emitKernelFunctionDirectives(*F, O);
630
632 O << ".noreturn";
633
634 OutStreamer->emitRawText(O.str());
635
636 VRegMapping.clear();
637 // Emit open brace for function body.
638 OutStreamer->emitRawText(StringRef("{\n"));
639 setAndEmitFunctionVirtualRegisters(*MF);
640 encodeDebugInfoRegisterNumbers(*MF);
641 // Emit initial .loc debug directive for correct relocation symbol data.
643}
644
646 bool Result = AsmPrinter::runOnMachineFunction(F);
647 // Emit closing brace for the body of function F.
648 // The closing brace must be emitted here because we need to emit additional
649 // debug labels/data after the last basic block.
650 // We need to emit the closing brace here because we don't have function that
651 // finished emission of the function body.
652 OutStreamer->emitRawText(StringRef("}\n"));
653 return Result;
654}
655
658 raw_svector_ostream O(Str);
659 emitDemotedVars(&MF->getFunction(), O);
660
661 const auto *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
662 for (const auto &[Id, CB] : MFI->getCallPrototypes())
663 emitCallPrototype(*CB, Id, O);
664
665 if (const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo())
666 for (const auto &[Idx, JT] : enumerate(MJTI->getJumpTables()))
667 emitJumpTable(JT, Idx, O);
668
669 OutStreamer->emitRawText(O.str());
670}
671
673 VRegMapping.clear();
674}
675
679 return OutContext.getOrCreateSymbol(Str);
680}
681
682void NVPTXAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
683 Register RegNo = MI->getOperand(0).getReg();
684 if (RegNo.isVirtual()) {
685 OutStreamer->AddComment(Twine("implicit-def: ") +
687 } else {
688 const NVPTXSubtarget &STI = MI->getMF()->getSubtarget<NVPTXSubtarget>();
689 OutStreamer->AddComment(Twine("implicit-def: ") +
690 STI.getRegisterInfo()->getName(RegNo));
691 }
692 OutStreamer->addBlankLine();
693}
694
695void NVPTXAsmPrinter::emitKernelFunctionDirectives(const Function &F,
696 raw_ostream &O) const {
697 // If the NVVM IR has some of reqntid* specified, then output
698 // the reqntid directive, and set the unspecified ones to 1.
699 // If none of Reqntid* is specified, don't output reqntid directive.
700 const auto ReqNTID = getReqNTID(F);
701 if (!ReqNTID.empty())
702 O << formatv(".reqntid {0:$[, ]}\n",
704
705 const auto MaxNTID = getMaxNTID(F);
706 if (!MaxNTID.empty())
707 O << formatv(".maxntid {0:$[, ]}\n",
709
710 if (const auto Mincta = getMinCTASm(F))
711 O << ".minnctapersm " << *Mincta << "\n";
712
713 if (const auto Maxnreg = getMaxNReg(F))
714 O << ".maxnreg " << *Maxnreg << "\n";
715
716 // .maxclusterrank directive requires SM_90 or higher, make sure that we
717 // filter it out for lower SM versions, as it causes a hard ptxas crash.
718 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
719 const NVPTXSubtarget *STI = &NTM.getSubtarget<NVPTXSubtarget>(F);
720
721 if (STI->getSmVersion() >= 90) {
722 const auto ClusterDim = getClusterDim(F);
724
725 if (!ClusterDim.empty()) {
726
727 if (!BlocksAreClusters)
728 O << ".explicitcluster\n";
729
730 if (ClusterDim[0] != 0) {
731 assert(llvm::all_of(ClusterDim, not_equal_to(0)) &&
732 "cluster_dim_x != 0 implies cluster_dim_y and cluster_dim_z "
733 "should be non-zero as well");
734
735 O << formatv(".reqnctapercluster {0:$[, ]}\n",
737 } else {
738 assert(llvm::all_of(ClusterDim, equal_to(0)) &&
739 "cluster_dim_x == 0 implies cluster_dim_y and cluster_dim_z "
740 "should be 0 as well");
741 }
742 }
743
744 if (BlocksAreClusters) {
745 LLVMContext &Ctx = F.getContext();
746 if (ReqNTID.empty() || ClusterDim.empty())
747 Ctx.diagnose(DiagnosticInfoUnsupported(
748 F, "blocksareclusters requires reqntid and cluster_dim attributes",
749 F.getSubprogram()));
750 else if (STI->getPTXVersion() < 90)
751 Ctx.diagnose(DiagnosticInfoUnsupported(
752 F, "blocksareclusters requires PTX version >= 9.0",
753 F.getSubprogram()));
754 else
755 O << ".blocksareclusters\n";
756 }
757
758 if (const auto Maxclusterrank = getMaxClusterRank(F))
759 O << ".maxclusterrank " << *Maxclusterrank << "\n";
760 }
761}
762
763std::string NVPTXAsmPrinter::getVirtualRegisterName(unsigned Reg) const {
764 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
765
766 std::string Name;
767 raw_string_ostream NameStr(Name);
768
769 VRegRCMap::const_iterator I = VRegMapping.find(RC);
770 assert(I != VRegMapping.end() && "Bad register class");
771 const DenseMap<unsigned, unsigned> &RegMap = I->second;
772
773 VRegMap::const_iterator VI = RegMap.find(Reg);
774 assert(VI != RegMap.end() && "Bad virtual register");
775 unsigned MappedVR = VI->second;
776
777 NameStr << getNVPTXRegClassStr(RC) << MappedVR;
778
779 return Name;
780}
781
782void NVPTXAsmPrinter::emitVirtualRegister(unsigned int vr,
783 raw_ostream &O) {
784 O << getVirtualRegisterName(vr);
785}
786
787void NVPTXAsmPrinter::emitAliasDeclaration(const GlobalAlias *GA,
788 raw_ostream &O) {
790 if (!F || isKernelFunction(*F) || F->isDeclaration())
792 "NVPTX aliasee must be a non-kernel function definition");
793
794 if (GA->hasLinkOnceLinkage() || GA->hasWeakLinkage() ||
796 report_fatal_error("NVPTX aliasee must not be '.weak'");
797
798 emitDeclarationWithName(F, getSymbol(GA), O);
799}
800
801void NVPTXAsmPrinter::emitDeclaration(const Function *F, raw_ostream &O) {
802 emitDeclarationWithName(F, getSymbol(F), O);
803}
804
805void NVPTXAsmPrinter::emitDeclarationWithName(const Function *F, MCSymbol *S,
806 raw_ostream &O) {
807 emitLinkageDirective(F, O);
808 if (isKernelFunction(*F))
809 O << ".entry ";
810 else
811 O << ".func ";
812 printReturnValStr(F, O);
813 S->print(O, MAI);
814 O << "\n";
815 emitFunctionParamList(F, O);
816 O << "\n";
818 O << ".noreturn";
819 O << ";\n";
820}
821
822static bool usedInGlobalVarDef(const Constant *C) {
823 if (!C)
824 return false;
825
827 return GV->getName() != "llvm.used";
828
829 for (const User *U : C->users())
830 if (const Constant *C = dyn_cast<Constant>(U))
832 return true;
833
834 return false;
835}
836
837static bool usedInOneFunc(const User *U, Function const *&OneFunc) {
838 if (const GlobalVariable *OtherGV = dyn_cast<GlobalVariable>(U))
839 if (OtherGV->getName() == "llvm.used")
840 return true;
841
842 if (const Instruction *I = dyn_cast<Instruction>(U)) {
843 if (const Function *CurFunc = I->getFunction()) {
844 if (OneFunc && (CurFunc != OneFunc))
845 return false;
846 OneFunc = CurFunc;
847 return true;
848 }
849 return false;
850 }
851
852 for (const User *UU : U->users())
853 if (!usedInOneFunc(UU, OneFunc))
854 return false;
855
856 return true;
857}
858
859/* Find out if a global variable can be demoted to local scope.
860 * Currently, this is valid for CUDA shared variables, which have local
861 * scope and global lifetime. So the conditions to check are :
862 * 1. Is the global variable in shared address space?
863 * 2. Does it have local linkage?
864 * 3. Is the global variable referenced only in one function?
865 */
866static bool canDemoteGlobalVar(const GlobalVariable *GV, Function const *&f) {
867 if (!GV->hasLocalLinkage())
868 return false;
870 return false;
871
872 const Function *oneFunc = nullptr;
873
874 bool flag = usedInOneFunc(GV, oneFunc);
875 if (!flag)
876 return false;
877 if (!oneFunc)
878 return false;
879 f = oneFunc;
880 return true;
881}
882
883static bool useFuncSeen(const Constant *C,
884 const SmallPtrSetImpl<const Function *> &SeenSet) {
885 for (const User *U : C->users()) {
886 if (const Constant *cu = dyn_cast<Constant>(U)) {
887 if (useFuncSeen(cu, SeenSet))
888 return true;
889 } else if (const Instruction *I = dyn_cast<Instruction>(U)) {
890 if (const Function *Caller = I->getFunction())
891 if (SeenSet.contains(Caller))
892 return true;
893 }
894 }
895 return false;
896}
897
898void NVPTXAsmPrinter::emitDeclarations(const Module &M, raw_ostream &O) {
899 SmallPtrSet<const Function *, 32> SeenSet;
900 for (const Function &F : M) {
901 if (F.getAttributes().hasFnAttr("nvptx-libcall-callee")) {
902 emitDeclaration(&F, O);
903 continue;
904 }
905
906 if (F.isDeclaration()) {
907 if (F.use_empty())
908 continue;
909 if (F.getIntrinsicID())
910 continue;
911 // An unrecognized intrinsic would produce an invalid PTX declaration. Let
912 // the user know that, and skip it.
913 if (F.isIntrinsic()) {
914 LLVMContext &Ctx = F.getContext();
915 Ctx.diagnose(DiagnosticInfoUnsupported(
916 F, "unknown intrinsic '" + F.getName() +
917 "' cannot be lowered by the NVPTX backend"));
918 continue;
919 }
920 emitDeclaration(&F, O);
921 continue;
922 }
923 for (const User *U : F.users()) {
924 if (const Constant *C = dyn_cast<Constant>(U)) {
925 if (usedInGlobalVarDef(C)) {
926 // The use is in the initialization of a global variable
927 // that is a function pointer, so print a declaration
928 // for the original function
929 emitDeclaration(&F, O);
930 break;
931 }
932 // Emit a declaration of this function if the function that
933 // uses this constant expr has already been seen.
934 if (useFuncSeen(C, SeenSet)) {
935 emitDeclaration(&F, O);
936 break;
937 }
938 }
939
940 if (!isa<Instruction>(U))
941 continue;
942 const Function *Caller = cast<Instruction>(U)->getFunction();
943 if (!Caller)
944 continue;
945
946 // If a caller has already been seen, then the caller is
947 // appearing in the module before the callee. so print out
948 // a declaration for the callee.
949 if (SeenSet.contains(Caller)) {
950 emitDeclaration(&F, O);
951 break;
952 }
953 }
954 SeenSet.insert(&F);
955 }
956 for (const GlobalAlias &GA : M.aliases())
957 emitAliasDeclaration(&GA, O);
958}
959
960void NVPTXAsmPrinter::emitStartOfAsmFile(Module &M) {
961 // Construct a default subtarget off of the TargetMachine defaults. The
962 // rest of NVPTX isn't friendly to change subtargets per function and
963 // so the default TargetMachine will have all of the options.
964 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
965 const NVPTXSubtarget *STI = NTM.getSubtargetImpl();
966
967 // Emit header before any dwarf directives are emitted below.
968 emitHeader(M, *STI);
969}
970
971/// Create NVPTX-specific DwarfDebug handler.
975
977 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
978 const NVPTXSubtarget &STI = *NTM.getSubtargetImpl();
979 if (M.alias_size() && (STI.getPTXVersion() < 63 || STI.getSmVersion() < 30))
980 report_fatal_error(".alias requires PTX version >= 6.3 and sm_30");
981
982 // We need to call the parent's one explicitly.
983 bool Result = AsmPrinter::doInitialization(M);
984
985 GlobalsEmitted = false;
986
987 return Result;
988}
989
990void NVPTXAsmPrinter::emitGlobals(const Module &M) {
991 SmallString<128> Str2;
992 raw_svector_ostream OS2(Str2);
993
994 emitDeclarations(M, OS2);
995
996 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
997 const NVPTXSubtarget &STI = *NTM.getSubtargetImpl();
998
999 // ptxas requires global symbols referenced by initializers to be known
1000 // before use. Acyclic dependencies can be handled by dependency-first
1001 // emission. Cyclic SCCs need compatible .extern declarations first.
1002 // Edges point from each global to the globals used by its initializer.
1003 // Reverse-topological SCC iteration therefore emits dependencies first.
1004 GlobalVariableDependencyGraph DependencyGraph(M);
1005 for (GlobalVariableSCCIterator I =
1006 GlobalVariableSCCIterator::begin(DependencyGraph.getEntryNode());
1007 !I.isAtEnd(); ++I) {
1009 I->end());
1010
1011 // Nothing points to the synthetic root, so it is always in its own SCC.
1012 if (!SCC.front()->GV) {
1013 assert(SCC.size() == 1 && "Synthetic root must be in its own SCC");
1014 continue;
1015 }
1016
1017 llvm::sort(SCC, [](const auto *LHS, const auto *RHS) {
1018 return LHS->ModuleOrder < RHS->ModuleOrder;
1019 });
1020
1021 const bool IsCyclic = I.hasCycle();
1022 DenseSet<const GlobalVariableDependencyNode *> ForwardDeclared;
1023 if (IsCyclic)
1024 for (const auto *Node : SCC)
1025 if (isForwardDeclarableGlobal(Node->GV))
1026 ForwardDeclared.insert(Node);
1027
1028 // Check that declarations break every cycle before writing any output.
1030 IsCyclic ? orderDefinitionsInSCC(SCC, ForwardDeclared)
1031 : SmallVector<const GlobalVariable *, 4>{SCC.front()->GV};
1032
1033 for (const auto *Node : SCC) {
1034 if (!ForwardDeclared.count(Node))
1035 continue;
1036 OS2 << ".extern ";
1037 emitPTXGlobalVariableDefinition(Node->GV, OS2, STI,
1038 /*EmitInitializer=*/false);
1039 OS2 << ";\n";
1040 }
1041
1042 for (const GlobalVariable *GV : OrderedGlobals)
1043 printModuleLevelGV(GV, OS2, /*ProcessDemoted=*/false, STI);
1044 }
1045
1046 OS2 << '\n';
1047
1048 OutStreamer->emitRawText(OS2.str());
1049}
1050
1051void NVPTXAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
1052 SmallString<128> Str;
1053 raw_svector_ostream OS(Str);
1054
1055 MCSymbol *Name = getSymbol(&GA);
1056
1057 OS << ".alias " << Name->getName() << ", " << GA.getAliaseeObject()->getName()
1058 << ";\n";
1059
1060 OutStreamer->emitRawText(OS.str());
1061}
1062
1063NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer() const {
1064 return static_cast<NVPTXTargetStreamer *>(OutStreamer->getTargetStreamer());
1065}
1066
1067static bool hasFullDebugInfo(Module &M) {
1068 for (DICompileUnit *CU : M.debug_compile_units()) {
1069 switch(CU->getEmissionKind()) {
1072 break;
1075 return true;
1076 }
1077 }
1078
1079 return false;
1080}
1081
1082void NVPTXAsmPrinter::emitHeader(Module &M, const NVPTXSubtarget &STI) {
1083 auto *TS = getTargetStreamer();
1084
1085 TS->emitBanner();
1086
1087 const unsigned PTXVersion = STI.getPTXVersion();
1088 TS->emitVersionDirective(PTXVersion);
1089
1090 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
1091 bool TexModeIndependent = NTM.getDrvInterface() == NVPTX::NVCL;
1092
1093 TS->emitTargetDirective(STI.getTargetName(), TexModeIndependent,
1094 hasFullDebugInfo(M));
1095 TS->emitAddressSizeDirective(M.getDataLayout().getPointerSizeInBits());
1096}
1097
1099 // If we did not emit any functions, then the global declarations have not
1100 // yet been emitted.
1101 if (!GlobalsEmitted) {
1102 emitGlobals(M);
1103 GlobalsEmitted = true;
1104 }
1105
1106 // call doFinalization
1107 bool ret = AsmPrinter::doFinalization(M);
1108
1110
1111 auto *TS =
1112 static_cast<NVPTXTargetStreamer *>(OutStreamer->getTargetStreamer());
1113 // Close the last emitted section
1114 if (hasDebugInfo()) {
1115 TS->closeLastSection();
1116 // Emit empty .debug_macinfo section for better support of the empty files.
1117 OutStreamer->emitRawText("\t.section\t.debug_macinfo\t{\t}");
1118 }
1119
1120 // Output last DWARF .file directives, if any.
1122
1123 return ret;
1124}
1125
1126// This function emits appropriate linkage directives for
1127// functions and global variables.
1128//
1129// extern function declaration -> .extern
1130// extern function definition -> .visible
1131// external global variable with init -> .visible
1132// external without init -> .extern
1133// appending -> not allowed, assert.
1134// for any linkage other than
1135// internal, private, linker_private,
1136// linker_private_weak, linker_private_weak_def_auto,
1137// we emit -> .weak.
1138
1139void NVPTXAsmPrinter::emitLinkageDirective(const GlobalValue *V,
1140 raw_ostream &O) {
1141 if (static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() == NVPTX::CUDA) {
1142 if (V->hasExternalLinkage()) {
1143 if (const auto *GVar = dyn_cast<GlobalVariable>(V))
1144 O << (GVar->hasInitializer() ? ".visible " : ".extern ");
1145 else if (V->isDeclaration())
1146 O << ".extern ";
1147 else
1148 O << ".visible ";
1149 } else if (V->hasAppendingLinkage()) {
1150 report_fatal_error("Symbol '" + (V->hasName() ? V->getName() : "") +
1151 "' has unsupported appending linkage type");
1152 } else if (!V->hasInternalLinkage() && !V->hasPrivateLinkage()) {
1153 O << ".weak ";
1154 }
1155 }
1156}
1157
1158void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar,
1159 raw_ostream &O, bool ProcessDemoted,
1160 const NVPTXSubtarget &STI) {
1161 // Skip metadata and LLVM intrinsic global variables.
1162 if (shouldSkipModuleLevelGlobal(*GVar))
1163 return;
1164
1165 if (GVar->hasExternalLinkage()) {
1166 if (GVar->hasInitializer())
1167 O << ".visible ";
1168 else
1169 O << ".extern ";
1170 } else if (STI.getPTXVersion() >= 50 && GVar->hasCommonLinkage() &&
1172 O << ".common ";
1173 } else if (GVar->hasLinkOnceLinkage() || GVar->hasWeakLinkage() ||
1175 GVar->hasCommonLinkage()) {
1176 O << ".weak ";
1177 }
1178
1179 const PTXOpaqueType OpaqueType = getPTXOpaqueType(*GVar);
1180
1181 if (OpaqueType == PTXOpaqueType::Texture) {
1182 O << ".global .texref " << getTextureName(*GVar) << ";\n";
1183 return;
1184 }
1185
1186 if (OpaqueType == PTXOpaqueType::Surface) {
1187 O << ".global .surfref " << getSurfaceName(*GVar) << ";\n";
1188 return;
1189 }
1190
1191 if (GVar->isDeclaration()) {
1192 // (extern) declarations, no definition or initializer
1193 // Currently the only known declaration is for an automatic __local
1194 // (.shared) promoted to global.
1195 emitPTXGlobalVariable(GVar, O, STI);
1196 O << ";\n";
1197 return;
1198 }
1199
1200 if (OpaqueType == PTXOpaqueType::Sampler) {
1201 O << ".global .samplerref " << getSamplerName(*GVar);
1202
1203 const Constant *Initializer = nullptr;
1204 if (GVar->hasInitializer())
1205 Initializer = GVar->getInitializer();
1206 const ConstantInt *CI = nullptr;
1207 if (Initializer)
1208 CI = dyn_cast<ConstantInt>(Initializer);
1209 if (CI) {
1210 unsigned sample = CI->getZExtValue();
1211
1212 O << " = { ";
1213
1214 for (int i = 0,
1215 addr = ((sample & __CLK_ADDRESS_MASK) >> __CLK_ADDRESS_BASE);
1216 i < 3; i++) {
1217 O << "addr_mode_" << i << " = ";
1218 switch (addr) {
1219 case 0:
1220 O << "wrap";
1221 break;
1222 case 1:
1223 O << "clamp_to_border";
1224 break;
1225 case 2:
1226 O << "clamp_to_edge";
1227 break;
1228 case 3:
1229 O << "wrap";
1230 break;
1231 case 4:
1232 O << "mirror";
1233 break;
1234 }
1235 O << ", ";
1236 }
1237 O << "filter_mode = ";
1238 switch ((sample & __CLK_FILTER_MASK) >> __CLK_FILTER_BASE) {
1239 case 0:
1240 O << "nearest";
1241 break;
1242 case 1:
1243 O << "linear";
1244 break;
1245 case 2:
1246 llvm_unreachable("Anisotropic filtering is not supported");
1247 default:
1248 O << "nearest";
1249 break;
1250 }
1251 if (!((sample & __CLK_NORMALIZED_MASK) >> __CLK_NORMALIZED_BASE)) {
1252 O << ", force_unnormalized_coords = 1";
1253 }
1254 O << " }";
1255 }
1256
1257 O << ";\n";
1258 return;
1259 }
1260
1261 if (GVar->hasPrivateLinkage()) {
1262 if (GVar->getName().starts_with("unrollpragma"))
1263 return;
1264
1265 // FIXME - need better way (e.g. Metadata) to avoid generating this global
1266 if (GVar->getName().starts_with("filename"))
1267 return;
1268 if (GVar->use_empty())
1269 return;
1270 }
1271
1272 const Function *DemotedFunc = nullptr;
1273 if (!ProcessDemoted && canDemoteGlobalVar(GVar, DemotedFunc)) {
1274 O << "// " << GVar->getName() << " has been demoted\n";
1275 localDecls[DemotedFunc].push_back(GVar);
1276 return;
1277 }
1278
1279 emitPTXGlobalVariableDefinition(GVar, O, STI, /*EmitInitializer=*/true);
1280 O << ";\n";
1281}
1282
1283void NVPTXAsmPrinter::emitPTXGlobalVariableDefinition(
1284 const GlobalVariable *GVar, raw_ostream &O, const NVPTXSubtarget &STI,
1285 bool EmitInitializer) {
1286 const DataLayout &DL = getDataLayout();
1287
1288 Type *ETy = GVar->getValueType();
1289
1290 O << ".";
1291 emitPTXAddressSpace(GVar->getAddressSpace(), O);
1292
1293 if (isManaged(*GVar)) {
1294 if (STI.getPTXVersion() < 40 || STI.getSmVersion() < 30)
1296 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1297 O << " .attribute(.managed)";
1298 }
1299
1300 O << " .align "
1301 << GVar->getAlign().value_or(DL.getPrefTypeAlign(ETy)).value();
1302
1303 if (ETy->isPointerTy() || ((ETy->isIntegerTy() || ETy->isFloatingPointTy()) &&
1304 ETy->getScalarSizeInBits() <= 64)) {
1305 O << " .";
1306 // Special case: ABI requires that we use .u8 for predicates
1307 if (ETy->isIntegerTy(1))
1308 O << "u8";
1309 else
1310 O << getPTXFundamentalTypeStr(ETy, false);
1311 O << " ";
1312 getSymbol(GVar)->print(O, MAI);
1313
1314 // Ptx allows variable initilization only for constant and global state
1315 // spaces.
1316 if (EmitInitializer && GVar->hasInitializer()) {
1317 if ((GVar->getAddressSpace() == ADDRESS_SPACE_GLOBAL) ||
1318 (GVar->getAddressSpace() == ADDRESS_SPACE_CONST)) {
1319 const Constant *Initializer = GVar->getInitializer();
1320 // 'undef' is treated as there is no value specified.
1321 if (!Initializer->isNullValue() && !isa<UndefValue>(Initializer)) {
1322 O << " = ";
1323 printScalarConstant(Initializer, O);
1324 }
1325 } else {
1326 // The frontend adds zero-initializer to device and constant variables
1327 // that don't have an initial value, and UndefValue to shared
1328 // variables, so skip warning for this case.
1329 if (!GVar->getInitializer()->isNullValue() &&
1330 !isa<UndefValue>(GVar->getInitializer())) {
1331 report_fatal_error("initial value of '" + GVar->getName() +
1332 "' is not allowed in addrspace(" +
1333 Twine(GVar->getAddressSpace()) + ")");
1334 }
1335 }
1336 }
1337 } else {
1338 // Although PTX has direct support for struct type and array type and
1339 // LLVM IR is very similar to PTX, the LLVM CodeGen does not support for
1340 // targets that support these high level field accesses. Structs, arrays
1341 // and vectors are lowered into arrays of bytes.
1342 switch (ETy->getTypeID()) {
1343 case Type::IntegerTyID: // Integers larger than 64 bits
1344 case Type::FP128TyID:
1345 case Type::StructTyID:
1346 case Type::ArrayTyID:
1347 case Type::FixedVectorTyID: {
1348 const uint64_t ElementSize = DL.getTypeStoreSize(ETy);
1349 // Ptx allows variable initilization only for constant and
1350 // global state spaces.
1351 if (((GVar->getAddressSpace() == ADDRESS_SPACE_GLOBAL) ||
1352 (GVar->getAddressSpace() == ADDRESS_SPACE_CONST)) &&
1353 GVar->hasInitializer()) {
1354 const Constant *Initializer = GVar->getInitializer();
1355 if (!isa<UndefValue>(Initializer) && !Initializer->isNullValue()) {
1356 AggBuffer aggBuffer(ElementSize, *this);
1357 bufferAggregateConstant(Initializer, &aggBuffer);
1358 if (aggBuffer.numSymbols()) {
1359 const unsigned int ptrSize = MAI.getCodePointerSize();
1360 if (ElementSize % ptrSize ||
1361 !aggBuffer.allSymbolsAligned(ptrSize)) {
1362 // Print in bytes and use the mask() operator for pointers.
1363 if (!STI.hasMaskOperator())
1365 "initialized packed aggregate with pointers '" +
1366 GVar->getName() +
1367 "' requires at least PTX ISA version 7.1");
1368 O << " .u8 ";
1369 getSymbol(GVar)->print(O, MAI);
1370 O << "[" << ElementSize << "]";
1371 if (EmitInitializer) {
1372 O << " = {";
1373 aggBuffer.printBytes(O);
1374 O << "}";
1375 }
1376 } else {
1377 O << " .u" << ptrSize * 8 << " ";
1378 getSymbol(GVar)->print(O, MAI);
1379 O << "[" << ElementSize / ptrSize << "]";
1380 if (EmitInitializer) {
1381 O << " = {";
1382 aggBuffer.printWords(O);
1383 O << "}";
1384 }
1385 }
1386 } else {
1387 O << " .b8 ";
1388 getSymbol(GVar)->print(O, MAI);
1389 O << "[" << ElementSize << "]";
1390 if (EmitInitializer) {
1391 O << " = {";
1392 aggBuffer.printBytes(O);
1393 O << "}";
1394 }
1395 }
1396 } else {
1397 O << " .b8 ";
1398 getSymbol(GVar)->print(O, MAI);
1399 if (ElementSize)
1400 O << "[" << ElementSize << "]";
1401 }
1402 } else {
1403 O << " .b8 ";
1404 getSymbol(GVar)->print(O, MAI);
1405 if (ElementSize)
1406 O << "[" << ElementSize << "]";
1407 }
1408 break;
1409 }
1410 default:
1411 llvm_unreachable("type not supported yet");
1412 }
1413 }
1414}
1415
1416void NVPTXAsmPrinter::AggBuffer::printSymbol(unsigned nSym, raw_ostream &os) {
1417 const Value *v = Symbols[nSym];
1418 const Value *v0 = SymbolsBeforeStripping[nSym];
1419 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
1420 MCSymbol *Name = AP.getSymbol(GVar);
1422 // Is v0 a generic pointer?
1423 bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
1424 if (EmitGeneric && isGenericPointer && !isa<Function>(v)) {
1425 os << "generic(";
1426 Name->print(os, AP.MAI);
1427 os << ")";
1428 } else {
1429 Name->print(os, AP.MAI);
1430 }
1431 } else if (const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(v0)) {
1432 const MCExpr *Expr = AP.lowerConstantForGV(CExpr, false);
1433 AP.printMCExpr(*Expr, os);
1434 } else
1435 llvm_unreachable("symbol type unknown");
1436}
1437
1438void NVPTXAsmPrinter::AggBuffer::printBytes(raw_ostream &os) {
1439 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1440 // Do not emit trailing zero initializers. They will be zero-initialized by
1441 // ptxas. This saves on both space requirements for the generated PTX and on
1442 // memory use by ptxas. (See:
1443 // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#global-state-space)
1444 unsigned int InitializerCount = Size;
1445 // TODO: symbols make this harder, but it would still be good to trim trailing
1446 // 0s for aggs with symbols as well.
1447 if (numSymbols() == 0)
1448 while (InitializerCount >= 1 && !buffer[InitializerCount - 1])
1449 InitializerCount--;
1450
1451 symbolPosInBuffer.push_back(InitializerCount);
1452 unsigned int nSym = 0;
1453 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1454 for (unsigned int pos = 0; pos < InitializerCount;) {
1455 if (pos)
1456 os << ", ";
1457 if (pos != nextSymbolPos) {
1458 os << (unsigned int)buffer[pos];
1459 ++pos;
1460 continue;
1461 }
1462 // Generate a per-byte mask() operator for the symbol, which looks like:
1463 // .global .u8 addr[] = {0xFF(foo), 0xFF00(foo), 0xFF0000(foo), ...};
1464 // See https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#initializers
1465 std::string symText;
1466 llvm::raw_string_ostream oss(symText);
1467 printSymbol(nSym, oss);
1468 for (unsigned i = 0; i < ptrSize; ++i) {
1469 if (i)
1470 os << ", ";
1471 llvm::write_hex(os, 0xFFULL << i * 8, HexPrintStyle::PrefixUpper);
1472 os << "(" << symText << ")";
1473 }
1474 pos += ptrSize;
1475 nextSymbolPos = symbolPosInBuffer[++nSym];
1476 assert(nextSymbolPos >= pos);
1477 }
1478}
1479
1480void NVPTXAsmPrinter::AggBuffer::printWords(raw_ostream &os) {
1481 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1482 symbolPosInBuffer.push_back(Size);
1483 unsigned int nSym = 0;
1484 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1485 assert(nextSymbolPos % ptrSize == 0);
1486 for (unsigned int pos = 0; pos < Size; pos += ptrSize) {
1487 if (pos)
1488 os << ", ";
1489 if (pos == nextSymbolPos) {
1490 printSymbol(nSym, os);
1491 nextSymbolPos = symbolPosInBuffer[++nSym];
1492 assert(nextSymbolPos % ptrSize == 0);
1493 assert(nextSymbolPos >= pos + ptrSize);
1494 } else if (ptrSize == 4)
1495 os << support::endian::read32le(&buffer[pos]);
1496 else
1497 os << support::endian::read64le(&buffer[pos]);
1498 }
1499}
1500
1501void NVPTXAsmPrinter::emitDemotedVars(const Function *F, raw_ostream &O) {
1502 auto It = localDecls.find(F);
1503 if (It == localDecls.end())
1504 return;
1505
1506 ArrayRef<const GlobalVariable *> GVars = It->second;
1507
1508 const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
1509 const NVPTXSubtarget &STI = *NTM.getSubtargetImpl();
1510
1511 for (const GlobalVariable *GV : GVars) {
1512 O << "\t// demoted variable\n\t";
1513 printModuleLevelGV(GV, O, /*processDemoted=*/true, STI);
1514 }
1515}
1516
1517void NVPTXAsmPrinter::emitPTXAddressSpace(unsigned int AddressSpace,
1518 raw_ostream &O) const {
1519 switch (AddressSpace) {
1521 O << "local";
1522 break;
1524 O << "global";
1525 break;
1527 O << "const";
1528 break;
1530 O << "shared";
1531 break;
1532 default:
1533 report_fatal_error("Bad address space found while emitting PTX: " +
1534 llvm::Twine(AddressSpace));
1535 break;
1536 }
1537}
1538
1539std::string
1540NVPTXAsmPrinter::getPTXFundamentalTypeStr(Type *Ty, bool useB4PTR) const {
1541 switch (Ty->getTypeID()) {
1542 case Type::IntegerTyID: {
1543 unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
1544 if (NumBits == 1)
1545 return "pred";
1546 if (NumBits <= 64) {
1547 std::string name = "u";
1548 return name + utostr(NumBits);
1549 }
1550 llvm_unreachable("Integer too large");
1551 break;
1552 }
1553 case Type::BFloatTyID:
1554 case Type::HalfTyID:
1555 // fp16 and bf16 are stored as .b16 for compatibility with pre-sm_53
1556 // PTX assembly.
1557 return "b16";
1558 case Type::FloatTyID:
1559 return "f32";
1560 case Type::DoubleTyID:
1561 return "f64";
1562 case Type::PointerTyID: {
1563 unsigned PtrSize = TM.getPointerSizeInBits(Ty->getPointerAddressSpace());
1564 assert((PtrSize == 64 || PtrSize == 32) && "Unexpected pointer size");
1565
1566 if (PtrSize == 64)
1567 if (useB4PTR)
1568 return "b64";
1569 else
1570 return "u64";
1571 else if (useB4PTR)
1572 return "b32";
1573 else
1574 return "u32";
1575 }
1576 default:
1577 break;
1578 }
1579 llvm_unreachable("unexpected type");
1580}
1581
1582void NVPTXAsmPrinter::emitPTXGlobalVariable(const GlobalVariable *GVar,
1583 raw_ostream &O,
1584 const NVPTXSubtarget &STI) {
1585 const DataLayout &DL = getDataLayout();
1586
1587 // GlobalVariables are always constant pointers themselves.
1588 Type *ETy = GVar->getValueType();
1589
1590 O << ".";
1591 emitPTXAddressSpace(GVar->getType()->getAddressSpace(), O);
1592 if (isManaged(*GVar)) {
1593 if (STI.getPTXVersion() < 40 || STI.getSmVersion() < 30)
1595 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1596
1597 O << " .attribute(.managed)";
1598 }
1599 O << " .align "
1600 << GVar->getAlign().value_or(DL.getPrefTypeAlign(ETy)).value();
1601
1602 // Special case for i128/fp128
1603 if (ETy->getScalarSizeInBits() == 128) {
1604 O << " .b8 ";
1605 getSymbol(GVar)->print(O, MAI);
1606 O << "[16]";
1607 return;
1608 }
1609
1610 if (ETy->isFloatingPointTy() || ETy->isIntOrPtrTy()) {
1611 O << " ." << getPTXFundamentalTypeStr(ETy) << " ";
1612 getSymbol(GVar)->print(O, MAI);
1613 return;
1614 }
1615
1616 int64_t ElementSize = 0;
1617
1618 // Although PTX has direct support for struct type and array type and LLVM IR
1619 // is very similar to PTX, the LLVM CodeGen does not support for targets that
1620 // support these high level field accesses. Structs and arrays are lowered
1621 // into arrays of bytes.
1622 switch (ETy->getTypeID()) {
1623 case Type::StructTyID:
1624 case Type::ArrayTyID:
1626 ElementSize = DL.getTypeStoreSize(ETy);
1627 O << " .b8 ";
1628 getSymbol(GVar)->print(O, MAI);
1629 O << "[";
1630 if (ElementSize) {
1631 O << ElementSize;
1632 }
1633 O << "]";
1634 break;
1635 default:
1636 llvm_unreachable("type not supported yet");
1637 }
1638}
1639
1640void NVPTXAsmPrinter::emitFunctionParamList(const Function *F, raw_ostream &O) {
1641 const DataLayout &DL = getDataLayout();
1642 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
1643 const auto *TLI = cast<NVPTXTargetLowering>(STI.getTargetLowering());
1644 const NVPTXMachineFunctionInfo *MFI =
1645 MF ? MF->getInfo<NVPTXMachineFunctionInfo>() : nullptr;
1646
1647 bool IsFirst = true;
1648 const bool IsKernelFunc = isKernelFunction(*F);
1649
1650 // Zero-sized arguments (e.g. empty structs) do not produce a parameter.
1651 // Number the emitted parameters contiguously, skipping the zero-sized ones,
1652 // so that the names match those used in LowerFormalArguments and the
1653 // contiguous numbering used by callers (see LowerCall).
1654 const auto NonEmptyArgs =
1655 make_filter_range(F->args(), [](const Argument &Arg) {
1656 return !Arg.getType()->isEmptyTy();
1657 });
1658
1659 if (NonEmptyArgs.empty() && !F->isVarArg()) {
1660 O << "()";
1661 return;
1662 }
1663
1664 O << "(\n";
1665
1666 for (const auto &[ParamIndex, Arg] : enumerate(NonEmptyArgs)) {
1667 Type *Ty = Arg.getType();
1668 const std::string ParamSym = TLI->getParamName(F, ParamIndex);
1669
1670 if (!IsFirst)
1671 O << ",\n";
1672
1673 IsFirst = false;
1674
1675 // Handle image/sampler parameters
1676 if (IsKernelFunc) {
1677 const PTXOpaqueType ArgOpaqueType = getPTXOpaqueType(Arg);
1678 if (ArgOpaqueType != PTXOpaqueType::None) {
1679 const bool EmitImgPtr = !MFI || !MFI->checkImageHandleSymbol(ParamSym);
1680 O << "\t.param ";
1681 if (EmitImgPtr)
1682 O << ".u64 .ptr ";
1683
1684 switch (ArgOpaqueType) {
1686 O << ".samplerref ";
1687 break;
1689 O << ".texref ";
1690 break;
1692 O << ".surfref ";
1693 break;
1695 llvm_unreachable("handled above");
1696 }
1697 O << ParamSym;
1698 continue;
1699 }
1700 }
1701
1702 if (Arg.hasByValAttr()) {
1703 // param has byVal attribute.
1704 Type *ETy = Arg.getParamByValType();
1705 assert(ETy && "Param should have byval type");
1706
1707 // Print .param .align <a> .b8 .param[size];
1708 // <a> = optimal alignment for the element type; always multiple of
1709 // PAL.getParamAlignment
1710 // size = typeallocsize of element type
1711 const unsigned ParamIdx = Arg.getArgNo() + AttributeList::FirstArgIndex;
1712 const Align OptimalAlign =
1713 IsKernelFunc ? getPTXParamAlign(F, ETy, ParamIdx, DL)
1714 : getDeviceByValParamAlign(F, ETy, ParamIdx, DL);
1715
1716 O << "\t.param .align " << OptimalAlign.value() << " .b8 " << ParamSym
1717 << "[" << DL.getTypeAllocSize(ETy) << "]";
1718 continue;
1719 }
1720
1721 if (shouldPassAsArray(Ty)) {
1722 // Just print .param .align <a> .b8 .param[size];
1723 // <a> = optimal alignment for the element type; always multiple of
1724 // PAL.getParamAlignment
1725 // size = typeallocsize of element type
1726 Align OptimalAlign = getPTXParamAlign(
1727 F, Ty, Arg.getArgNo() + AttributeList::FirstArgIndex, DL);
1728
1729 O << "\t.param .align " << OptimalAlign.value() << " .b8 " << ParamSym
1730 << "[" << DL.getTypeAllocSize(Ty) << "]";
1731
1732 continue;
1733 }
1734 // Just a scalar
1735 auto *PTy = dyn_cast<PointerType>(Ty);
1736 unsigned PTySizeInBits = 0;
1737 if (PTy) {
1738 PTySizeInBits =
1739 TLI->getPointerTy(DL, PTy->getAddressSpace()).getSizeInBits();
1740 assert(PTySizeInBits && "Invalid pointer size");
1741 }
1742
1743 if (IsKernelFunc) {
1744 if (PTy) {
1745 O << "\t.param .u" << PTySizeInBits << " .ptr";
1746
1747 switch (PTy->getAddressSpace()) {
1748 default:
1749 break;
1751 O << " .global";
1752 break;
1754 O << " .shared";
1755 break;
1757 O << " .const";
1758 break;
1760 O << " .local";
1761 break;
1762 }
1763
1764 O << " .align " << Arg.getParamAlign().valueOrOne().value() << " "
1765 << ParamSym;
1766 continue;
1767 }
1768
1769 // non-pointer scalar to kernel func
1770 O << "\t.param .";
1771 // Special case: predicate operands become .u8 types
1772 if (Ty->isIntegerTy(1))
1773 O << "u8";
1774 else
1775 O << getPTXFundamentalTypeStr(Ty);
1776 O << " " << ParamSym;
1777 continue;
1778 }
1779 // Non-kernel function, just print .param .b<size> for ABI
1780 // and .reg .b<size> for non-ABI
1781 unsigned Size;
1782 if (auto *ITy = dyn_cast<IntegerType>(Ty)) {
1783 Size = promoteScalarArgumentSize(ITy->getBitWidth());
1784 } else if (PTy) {
1785 assert(PTySizeInBits && "Invalid pointer size");
1786 Size = PTySizeInBits;
1787 } else
1789 O << "\t.param .b" << Size << " " << ParamSym;
1790 }
1791
1792 if (F->isVarArg()) {
1793 if (!IsFirst)
1794 O << ",\n";
1795 O << "\t.param .align " << STI.getMaxRequiredAlignment() << " .b8 "
1796 << TLI->getParamName(F, /* vararg */ -1) << "[]";
1797 }
1798
1799 O << "\n)";
1800}
1801
1802void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1803 const MachineFunction &MF) {
1804 SmallString<128> Str;
1805 raw_svector_ostream O(Str);
1806
1807 // Map the global virtual register number to a register class specific
1808 // virtual register number starting from 1 with that class.
1809 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1810
1811 // Emit the Fake Stack Object
1812 const MachineFrameInfo &MFI = MF.getFrameInfo();
1813 int64_t NumBytes = MFI.getStackSize();
1814 if (NumBytes) {
1815 O << "\t.local .align " << MFI.getMaxAlign().value() << " .b8 \t"
1816 << DEPOTNAME << getFunctionNumber() << "[" << NumBytes << "];\n";
1817 const bool Is64Bit =
1818 static_cast<const NVPTXTargetMachine &>(MF.getTarget()).is64Bit();
1819 const bool IsLocal64 =
1820 MF.getDataLayout().getPointerSizeInBits(ADDRESS_SPACE_LOCAL) == 64;
1821 O << "\t.reg .b" << (Is64Bit ? 64 : 32) << " \t%SP;\n"
1822 << "\t.reg .b" << (IsLocal64 ? 64 : 32) << " \t%SPL;\n";
1823 }
1824
1825 // Go through all virtual registers to establish the mapping between the
1826 // global virtual
1827 // register number and the per class virtual register number.
1828 // We use the per class virtual register number in the ptx output.
1829 for (unsigned I : llvm::seq(MRI->getNumVirtRegs())) {
1831 if (MRI->use_empty(VR) && MRI->def_empty(VR))
1832 continue;
1833 auto &RCRegMap = VRegMapping[MRI->getRegClass(VR)];
1834 RCRegMap[VR] = RCRegMap.size() + 1;
1835 }
1836
1837 // Emit declaration of the virtual registers or 'physical' registers for
1838 // each register class
1839 for (const TargetRegisterClass &RC : TRI->regclasses()) {
1840 const unsigned N = VRegMapping[&RC].size();
1841
1842 // Only declare those registers that may be used.
1843 if (N) {
1844 const StringRef RCName = getNVPTXRegClassName(&RC);
1845 const StringRef RCStr = getNVPTXRegClassStr(&RC);
1846 O << "\t.reg " << RCName << " \t" << RCStr << "<" << (N + 1) << ">;\n";
1847 }
1848 }
1849
1850 OutStreamer->emitRawText(O.str());
1851}
1852
1853/// Translate virtual register numbers in DebugInfo locations to their printed
1854/// encodings, as used by CUDA-GDB.
1855void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
1856 const MachineFunction &MF) {
1857 const NVPTXSubtarget &STI = MF.getSubtarget<NVPTXSubtarget>();
1858 const NVPTXRegisterInfo *registerInfo = STI.getRegisterInfo();
1859
1860 // Clear the old mapping, and add the new one. This mapping is used after the
1861 // printing of the current function is complete, but before the next function
1862 // is printed.
1863 registerInfo->clearDebugRegisterMap();
1864
1865 for (auto &classMap : VRegMapping) {
1866 for (auto &registerMapping : classMap.getSecond()) {
1867 auto reg = registerMapping.getFirst();
1868 registerInfo->addToDebugRegisterMap(reg, getVirtualRegisterName(reg));
1869 }
1870 }
1871}
1872
1873void NVPTXAsmPrinter::printFPConstant(const ConstantFP *Fp,
1874 raw_ostream &O) const {
1875 APFloat APF = APFloat(Fp->getValueAPF()); // make a copy
1876 bool ignored;
1877 unsigned int numHex;
1878 const char *lead;
1879
1880 if (Fp->getType()->getTypeID() == Type::FloatTyID) {
1881 numHex = 8;
1882 lead = "0f";
1884 } else if (Fp->getType()->getTypeID() == Type::DoubleTyID) {
1885 numHex = 16;
1886 lead = "0d";
1888 } else
1889 llvm_unreachable("unsupported fp type");
1890
1891 APInt API = APF.bitcastToAPInt();
1892 O << lead << format_hex_no_prefix(API.getZExtValue(), numHex, /*Upper=*/true);
1893}
1894
1895void NVPTXAsmPrinter::printScalarConstant(const Constant *CPV, raw_ostream &O) {
1896 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
1897 O << CI->getValue();
1898 return;
1899 }
1900 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV)) {
1901 printFPConstant(CFP, O);
1902 return;
1903 }
1904 if (isa<ConstantPointerNull>(CPV)) {
1905 O << "0";
1906 return;
1907 }
1908 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
1909 const bool IsNonGenericPointer = GVar->getAddressSpace() != 0;
1910 if (EmitGeneric && !isa<Function>(CPV) && !IsNonGenericPointer) {
1911 O << "generic(";
1912 getSymbol(GVar)->print(O, MAI);
1913 O << ")";
1914 } else {
1915 getSymbol(GVar)->print(O, MAI);
1916 }
1917 return;
1918 }
1919 if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1920 const MCExpr *E = lowerConstantForGV(cast<Constant>(Cexpr), false);
1921 printMCExpr(*E, O);
1922 return;
1923 }
1924 llvm_unreachable("Not scalar type found in printScalarConstant()");
1925}
1926
1927void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
1928 AggBuffer *AggBuffer) {
1929 const DataLayout &DL = getDataLayout();
1930 int AllocSize = DL.getTypeAllocSize(CPV->getType());
1931 if (isa<UndefValue>(CPV) || CPV->isNullValue()) {
1932 // Non-zero Bytes indicates that we need to zero-fill everything. Otherwise,
1933 // only the space allocated by CPV.
1934 AggBuffer->addZeros(Bytes ? Bytes : AllocSize);
1935 return;
1936 }
1937
1938 // Helper for filling AggBuffer with APInts.
1939 auto AddIntToBuffer = [AggBuffer, Bytes](const APInt &Val) {
1940 size_t NumBytes = (Val.getBitWidth() + 7) / 8;
1941 SmallVector<unsigned char, 16> Buf(NumBytes);
1942 // `extractBitsAsZExtValue` does not allow the extraction of bits beyond the
1943 // input's bit width, and i1 arrays may not have a length that is a multuple
1944 // of 8. We handle the last byte separately, so we never request out of
1945 // bounds bits.
1946 for (unsigned I = 0; I < NumBytes - 1; ++I) {
1947 Buf[I] = Val.extractBitsAsZExtValue(8, I * 8);
1948 }
1949 size_t LastBytePosition = (NumBytes - 1) * 8;
1950 size_t LastByteBits = Val.getBitWidth() - LastBytePosition;
1951 Buf[NumBytes - 1] =
1952 Val.extractBitsAsZExtValue(LastByteBits, LastBytePosition);
1953 AggBuffer->addBytes(Buf.data(), NumBytes, Bytes);
1954 };
1955
1956 switch (CPV->getType()->getTypeID()) {
1957 case Type::IntegerTyID:
1958 if (const auto *CI = dyn_cast<ConstantInt>(CPV)) {
1959 AddIntToBuffer(CI->getValue());
1960 break;
1961 }
1962 if (const auto *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1963 if (const auto *CI =
1965 AddIntToBuffer(CI->getValue());
1966 break;
1967 }
1968 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1969 Value *V = Cexpr->getOperand(0)->stripPointerCasts();
1970 AggBuffer->addSymbol(V, Cexpr->getOperand(0));
1971 AggBuffer->addZeros(AllocSize);
1972 break;
1973 }
1974 // A symbol-relative integer whose offset is applied outside the
1975 // ptrtoint, e.g. add(ptrtoint(@g), C). It can't fold to a ConstantInt
1976 // because it references a symbol; emit it through lowerConstantForGV, the
1977 // same path scalar symbol-relative integer globals use.
1978 AggBuffer->addSymbol(Cexpr, Cexpr);
1979 AggBuffer->addZeros(AllocSize);
1980 break;
1981 }
1982 llvm_unreachable("unsupported integer const type");
1983 break;
1984
1985 case Type::HalfTyID:
1986 case Type::BFloatTyID:
1987 case Type::FloatTyID:
1988 case Type::DoubleTyID:
1989 AddIntToBuffer(cast<ConstantFP>(CPV)->getValueAPF().bitcastToAPInt());
1990 break;
1991
1992 case Type::PointerTyID: {
1993 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
1994 AggBuffer->addSymbol(GVar, GVar);
1995 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1996 const Value *v = Cexpr->stripPointerCasts();
1997 AggBuffer->addSymbol(v, Cexpr);
1998 }
1999 AggBuffer->addZeros(AllocSize);
2000 break;
2001 }
2002
2003 case Type::ArrayTyID:
2005 case Type::StructTyID: {
2007 // bufferAggregateConstant doesn't emit tail-padding, i.e. it writes
2008 // `store_size` bytes, not `alloc_size` bytes. Do it ourselves here.
2009 unsigned StartPos = AggBuffer->getCurpos();
2010 bufferAggregateConstant(CPV, AggBuffer);
2011 unsigned Written = AggBuffer->getCurpos() - StartPos;
2012 unsigned SlotSize = std::max<int>(Bytes, AllocSize);
2013 if (SlotSize > Written)
2014 AggBuffer->addZeros(SlotSize - Written);
2015 } else if (isa<ConstantAggregateZero>(CPV))
2016 AggBuffer->addZeros(Bytes);
2017 else
2018 llvm_unreachable("Unexpected Constant type");
2019 break;
2020 }
2021
2022 default:
2023 llvm_unreachable("unsupported type");
2024 }
2025}
2026
2027void NVPTXAsmPrinter::bufferAggregateConstant(const Constant *CPV,
2028 AggBuffer *aggBuffer) {
2029 const DataLayout &DL = getDataLayout();
2030
2031 auto ExtendBuffer = [](APInt Val, AggBuffer *Buffer) {
2032 unsigned NumBytes = divideCeil(Val.getBitWidth(), 8);
2033 for (unsigned I : llvm::seq(NumBytes)) {
2034 unsigned NumBits = std::min(8u, Val.getBitWidth() - I * 8);
2035 Buffer->addByte(Val.extractBitsAsZExtValue(NumBits, I * 8));
2036 }
2037 };
2038
2039 // Integer or floating point vector splats.
2041 if (auto *VTy = dyn_cast<FixedVectorType>(CPV->getType())) {
2042 for (unsigned I : llvm::seq(VTy->getNumElements()))
2043 bufferLEByte(CPV->getAggregateElement(I), 0, aggBuffer);
2044 return;
2045 }
2046 }
2047
2048 // Integers of arbitrary width
2049 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
2050 assert(CI->getType()->isIntegerTy() && "Expected integer constant!");
2051 ExtendBuffer(CI->getValue(), aggBuffer);
2052 return;
2053 }
2054
2055 // f128
2056 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV)) {
2057 assert(CFP->getType()->isFloatingPointTy() && "Expected fp constant!");
2058 if (CFP->getType()->isFP128Ty()) {
2059 ExtendBuffer(CFP->getValueAPF().bitcastToAPInt(), aggBuffer);
2060 return;
2061 }
2062 }
2063
2064 // Buffer arrays one element at a time.
2065 if (isa<ConstantArray>(CPV)) {
2066 for (const auto &Op : CPV->operands())
2067 bufferLEByte(cast<Constant>(Op), 0, aggBuffer);
2068 return;
2069 }
2070
2071 // Constant vectors
2072 if (const auto *CVec = dyn_cast<ConstantVector>(CPV)) {
2073 bufferAggregateConstVec(CVec, aggBuffer);
2074 return;
2075 }
2076
2077 if (const auto *CDS = dyn_cast<ConstantDataSequential>(CPV)) {
2078 for (unsigned I : llvm::seq(CDS->getNumElements()))
2079 bufferLEByte(cast<Constant>(CDS->getElementAsConstant(I)), 0, aggBuffer);
2080 return;
2081 }
2082
2083 if (isa<ConstantStruct>(CPV)) {
2084 if (CPV->getNumOperands()) {
2085 StructType *ST = cast<StructType>(CPV->getType());
2086 for (unsigned I : llvm::seq(CPV->getNumOperands())) {
2087 int EndOffset = (I + 1 == CPV->getNumOperands())
2088 ? DL.getStructLayout(ST)->getElementOffset(0) +
2089 DL.getTypeAllocSize(ST)
2090 : DL.getStructLayout(ST)->getElementOffset(I + 1);
2091 int Bytes = EndOffset - DL.getStructLayout(ST)->getElementOffset(I);
2092 bufferLEByte(cast<Constant>(CPV->getOperand(I)), Bytes, aggBuffer);
2093 }
2094 }
2095 return;
2096 }
2097 llvm_unreachable("unsupported constant type in printAggregateConstant()");
2098}
2099
2100void NVPTXAsmPrinter::bufferAggregateConstVec(const ConstantVector *CV,
2101 AggBuffer *aggBuffer) {
2102 unsigned NumElems = CV->getType()->getNumElements();
2103 const unsigned BuffSize = aggBuffer->getBufferSize();
2104
2105 // Buffer one element at a time if we have allocated enough buffer space.
2106 if (BuffSize >= NumElems) {
2107 for (const auto &Op : CV->operands())
2108 bufferLEByte(cast<Constant>(Op), 0, aggBuffer);
2109 return;
2110 }
2111
2112 // Sub-byte datatypes will have more elements than bytes allocated for the
2113 // buffer. Merge consecutive elements to form a full byte. We expect that 8 %
2114 // sub-byte-elem-size should be 0 and current expected usage is for i4 (for
2115 // e2m1-fp4 types).
2116 Type *ElemTy = CV->getType()->getElementType();
2117 assert(ElemTy->isIntegerTy() && "Expected integer data type.");
2118 unsigned ElemTySize = ElemTy->getPrimitiveSizeInBits();
2119 assert(ElemTySize < 8 && "Expected sub-byte data type.");
2120 assert(8 % ElemTySize == 0 && "Element type size must evenly divide a byte.");
2121 // Number of elements to merge to form a full byte.
2122 unsigned NumElemsPerByte = 8 / ElemTySize;
2123 unsigned NumCompleteBytes = NumElems / NumElemsPerByte;
2124 unsigned NumTailElems = NumElems % NumElemsPerByte;
2125
2126 // Helper lambda to constant-fold sub-vector of sub-byte type elements into
2127 // i8. Start and end indices of the sub-vector is provided, along with number
2128 // of padding zeros if required.
2129 auto ConvertSubCVtoInt8 = [this, &ElemTy](const ConstantVector *CV,
2130 unsigned Start, unsigned End,
2131 unsigned NumPaddingZeros = 0) {
2132 // Collect elements to create sub-vector.
2133 SmallVector<Constant *, 8> SubCVElems;
2134 for (unsigned I : llvm::seq(Start, End))
2135 SubCVElems.push_back(CV->getAggregateElement(I));
2136
2137 // Optionally pad with zeros.
2138 if (NumPaddingZeros)
2139 SubCVElems.append(NumPaddingZeros, ConstantInt::getNullValue(ElemTy));
2140
2141 auto SubCV = ConstantVector::get(SubCVElems);
2142 Type *Int8Ty = IntegerType::get(SubCV->getContext(), 8);
2143
2144 // Merge elements of the sub-vector using ConstantFolding.
2145 ConstantInt *MergedElem =
2147 ConstantExpr::getBitCast(const_cast<Constant *>(SubCV), Int8Ty),
2148 getDataLayout()));
2149
2150 if (!MergedElem)
2152 "Cannot lower vector global with unusual element type");
2153
2154 return MergedElem;
2155 };
2156
2157 // Iterate through elements of vector one chunk at a time and buffer that
2158 // chunk.
2159 for (unsigned ByteIdx : llvm::seq(NumCompleteBytes))
2160 bufferLEByte(ConvertSubCVtoInt8(CV, ByteIdx * NumElemsPerByte,
2161 (ByteIdx + 1) * NumElemsPerByte),
2162 0, aggBuffer);
2163
2164 // For unevenly sized vectors add tail padding zeros.
2165 if (NumTailElems > 0)
2166 bufferLEByte(ConvertSubCVtoInt8(CV, NumElems - NumTailElems, NumElems,
2167 NumElemsPerByte - NumTailElems),
2168 0, aggBuffer);
2169}
2170
2171/// lowerConstantForGV - Return an MCExpr for the given Constant. This is mostly
2172/// a copy from AsmPrinter::lowerConstant, except customized to only handle
2173/// expressions that are representable in PTX and create
2174/// NVPTXGenericMCSymbolRefExpr nodes for addrspacecast instructions.
2175const MCExpr *
2176NVPTXAsmPrinter::lowerConstantForGV(const Constant *CV,
2177 bool ProcessingGeneric) const {
2178 MCContext &Ctx = OutContext;
2179
2180 if (CV->isNullValue() || isa<UndefValue>(CV))
2181 return MCConstantExpr::create(0, Ctx);
2182
2183 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
2184 return MCConstantExpr::create(CI->getZExtValue(), Ctx);
2185
2186 if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
2187 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(getSymbol(GV), Ctx);
2188 if (ProcessingGeneric)
2189 return NVPTXGenericMCSymbolRefExpr::create(Expr, Ctx);
2190 return Expr;
2191 }
2192
2193 const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
2194 if (!CE) {
2195 llvm_unreachable("Unknown constant value to lower!");
2196 }
2197
2198 switch (CE->getOpcode()) {
2199 default:
2200 break; // Error
2201
2202 case Instruction::AddrSpaceCast: {
2203 // Strip the addrspacecast and pass along the operand
2204 PointerType *DstTy = cast<PointerType>(CE->getType());
2205 if (DstTy->getAddressSpace() == 0)
2206 return lowerConstantForGV(cast<const Constant>(CE->getOperand(0)), true);
2207
2208 break; // Error
2209 }
2210
2211 case Instruction::GetElementPtr: {
2212 const DataLayout &DL = getDataLayout();
2213
2214 // Generate a symbolic expression for the byte address
2215 APInt OffsetAI(DL.getPointerTypeSizeInBits(CE->getType()), 0);
2216 cast<GEPOperator>(CE)->accumulateConstantOffset(DL, OffsetAI);
2217
2218 const MCExpr *Base = lowerConstantForGV(CE->getOperand(0),
2219 ProcessingGeneric);
2220 if (!OffsetAI)
2221 return Base;
2222
2223 int64_t Offset = OffsetAI.getSExtValue();
2225 Ctx);
2226 }
2227
2228 case Instruction::Trunc:
2229 // We emit the value and depend on the assembler to truncate the generated
2230 // expression properly. This is important for differences between
2231 // blockaddress labels. Since the two labels are in the same function, it
2232 // is reasonable to treat their delta as a 32-bit value.
2233 [[fallthrough]];
2234 case Instruction::BitCast:
2235 return lowerConstantForGV(CE->getOperand(0), ProcessingGeneric);
2236
2237 case Instruction::IntToPtr: {
2238 const DataLayout &DL = getDataLayout();
2239
2240 // Handle casts to pointers by changing them into casts to the appropriate
2241 // integer type. This promotes constant folding and simplifies this code.
2242 Constant *Op = CE->getOperand(0);
2243 Op = ConstantFoldIntegerCast(Op, DL.getIntPtrType(CV->getType()),
2244 /*IsSigned*/ false, DL);
2245 if (Op)
2246 return lowerConstantForGV(Op, ProcessingGeneric);
2247
2248 break; // Error
2249 }
2250
2251 case Instruction::PtrToInt: {
2252 const DataLayout &DL = getDataLayout();
2253
2254 // Support only foldable casts to/from pointers that can be eliminated by
2255 // changing the pointer to the appropriately sized integer type.
2256 Constant *Op = CE->getOperand(0);
2257 Type *Ty = CE->getType();
2258
2259 const MCExpr *OpExpr = lowerConstantForGV(Op, ProcessingGeneric);
2260
2261 // We can emit the pointer value into this slot if the slot is an
2262 // integer slot equal to the size of the pointer.
2263 if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType()))
2264 return OpExpr;
2265
2266 // Otherwise the pointer is smaller than the resultant integer, mask off
2267 // the high bits so we are sure to get a proper truncation if the input is
2268 // a constant expr.
2269 unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType());
2270 const MCExpr *MaskExpr = MCConstantExpr::create(~0ULL >> (64-InBits), Ctx);
2271 return MCBinaryExpr::createAnd(OpExpr, MaskExpr, Ctx);
2272 }
2273
2274 // The MC library also has a right-shift operator, but it isn't consistently
2275 // signed or unsigned between different targets.
2276 case Instruction::Add: {
2277 const MCExpr *LHS = lowerConstantForGV(CE->getOperand(0), ProcessingGeneric);
2278 const MCExpr *RHS = lowerConstantForGV(CE->getOperand(1), ProcessingGeneric);
2279 switch (CE->getOpcode()) {
2280 default: llvm_unreachable("Unknown binary operator constant cast expr");
2281 case Instruction::Add: return MCBinaryExpr::createAdd(LHS, RHS, Ctx);
2282 }
2283 }
2284 }
2285
2286 // If the code isn't optimized, there may be outstanding folding
2287 // opportunities. Attempt to fold the expression using DataLayout as a
2288 // last resort before giving up.
2290 if (C != CE)
2291 return lowerConstantForGV(C, ProcessingGeneric);
2292
2293 // Otherwise report the problem to the user.
2294 std::string S;
2295 raw_string_ostream OS(S);
2296 OS << "Unsupported expression in static initializer: ";
2297 CE->printAsOperand(OS, /*PrintType=*/false,
2298 !MF ? nullptr : MF->getFunction().getParent());
2299 report_fatal_error(Twine(OS.str()));
2300}
2301
2302void NVPTXAsmPrinter::printMCExpr(const MCExpr &Expr, raw_ostream &OS) const {
2303 OutContext.getAsmInfo().printExpr(OS, Expr);
2304}
2305
2306/// PrintAsmOperand - Print out an operand for an inline asm expression.
2307///
2308bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
2309 const char *ExtraCode, raw_ostream &O) {
2310 if (ExtraCode && ExtraCode[0]) {
2311 if (ExtraCode[1] != 0)
2312 return true; // Unknown modifier.
2313
2314 switch (ExtraCode[0]) {
2315 default:
2316 // See if this is a generic print operand
2317 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
2318 case 'r':
2319 break;
2320 }
2321 }
2322
2323 printOperand(MI, OpNo, O);
2324
2325 return false;
2326}
2327
2328bool NVPTXAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
2329 unsigned OpNo,
2330 const char *ExtraCode,
2331 raw_ostream &O) {
2332 if (ExtraCode && ExtraCode[0])
2333 return true; // Unknown modifier
2334
2335 O << '[';
2336 printMemOperand(MI, OpNo, O);
2337 O << ']';
2338
2339 return false;
2340}
2341
2342void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
2343 raw_ostream &O) {
2344 const MachineOperand &MO = MI->getOperand(OpNum);
2345 switch (MO.getType()) {
2347 if (MO.getReg().isPhysical()) {
2348 if (MO.getReg() == NVPTX::VRDepot)
2350 else
2352 } else {
2353 emitVirtualRegister(MO.getReg(), O);
2354 }
2355 break;
2356
2358 O << MO.getImm();
2359 break;
2360
2362 printFPConstant(MO.getFPImm(), O);
2363 break;
2364
2366 PrintSymbolOperand(MO, O);
2367 break;
2368
2370 MO.getMBB()->getSymbol()->print(O, MAI);
2371 break;
2372
2373 default:
2374 llvm_unreachable("Operand type not supported.");
2375 }
2376}
2377
2378void NVPTXAsmPrinter::printMemOperand(const MachineInstr *MI, unsigned OpNum,
2379 raw_ostream &O, const char *Modifier) {
2380 printOperand(MI, OpNum, O);
2381
2382 if (Modifier && strcmp(Modifier, "add") == 0) {
2383 O << ", ";
2384 printOperand(MI, OpNum + 1, O);
2385 } else {
2386 if (MI->getOperand(OpNum + 1).isImm() &&
2387 MI->getOperand(OpNum + 1).getImm() == 0)
2388 return; // don't print ',0' or '+0'
2389 O << "+";
2390 printOperand(MI, OpNum + 1, O);
2391 }
2392}
2393
2394/// Returns true if \p Line begins with an alphabetic character or underscore,
2395/// indicating it is a PTX instruction that should receive a .loc directive.
2396static bool isPTXInstruction(StringRef Line) {
2397 StringRef Trimmed = Line.ltrim();
2398 return !Trimmed.empty() &&
2399 (std::isalpha(static_cast<unsigned char>(Trimmed[0])) ||
2400 Trimmed[0] == '_');
2401}
2402
2403/// Returns the DILocation for an inline asm MachineInstr if debug line info
2404/// should be emitted, or nullptr otherwise.
2406 if (!MI || !MI->getDebugLoc())
2407 return nullptr;
2408 const DISubprogram *SP = MI->getMF()->getFunction().getSubprogram();
2409 if (!SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug)
2410 return nullptr;
2411 const DILocation *DL = MI->getDebugLoc();
2412 if (!DL->getFile() || !DL->getLine())
2413 return nullptr;
2414 return DL;
2415}
2416
2417namespace {
2418struct InlineAsmInliningContext {
2419 MCSymbol *FuncNameSym = nullptr;
2420 unsigned FileIA = 0;
2421 unsigned LineIA = 0;
2422 unsigned ColIA = 0;
2423
2424 bool hasInlinedAt() const { return FuncNameSym != nullptr; }
2425};
2426} // namespace
2427
2428/// Resolves the enhanced-lineinfo inlining context for an inline asm debug
2429/// location. Returns a default (empty) context if inlining info is unavailable.
2430static InlineAsmInliningContext
2432 NVPTXDwarfDebug *NVDD, MCStreamer &Streamer,
2433 unsigned CUID) {
2434 InlineAsmInliningContext Ctx;
2435 const DILocation *InlinedAt = DL->getInlinedAt();
2436 if (!InlinedAt || !InlinedAt->getFile() || !NVDD ||
2437 !NVDD->isEnhancedLineinfo(MF))
2438 return Ctx;
2439 const auto *SubProg = getDISubprogram(DL->getScope());
2440 if (!SubProg)
2441 return Ctx;
2442 Ctx.FuncNameSym = NVDD->getOrCreateFuncNameSymbol(SubProg->getLinkageName());
2443 Ctx.FileIA = Streamer.emitDwarfFileDirective(
2444 0, InlinedAt->getFile()->getDirectory(),
2445 InlinedAt->getFile()->getFilename(), std::nullopt, std::nullopt, CUID);
2446 Ctx.LineIA = InlinedAt->getLine();
2447 Ctx.ColIA = InlinedAt->getColumn();
2448 return Ctx;
2449}
2450
2451void NVPTXAsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
2452 const MCTargetOptions &MCOptions,
2453 const MDNode *LocMDNode,
2454 InlineAsm::AsmDialect Dialect,
2455 const MachineInstr *MI) {
2456 assert(!Str.empty() && "Can't emit empty inline asm block");
2457 if (Str.back() == 0)
2458 Str = Str.substr(0, Str.size() - 1);
2459
2460 auto emitAsmStr = [&](StringRef AsmStr) {
2462 OutStreamer->emitRawText(AsmStr);
2463 emitInlineAsmEnd(STI, nullptr, MI);
2464 };
2465
2466 const DILocation *DL = getInlineAsmDebugLoc(MI);
2467 if (!DL) {
2468 emitAsmStr(Str);
2469 return;
2470 }
2471
2472 const DIFile *File = DL->getFile();
2473 unsigned Line = DL->getLine();
2474 const unsigned Column = DL->getColumn();
2475 const unsigned CUID = OutStreamer->getContext().getDwarfCompileUnitID();
2476 const unsigned FileNumber = OutStreamer->emitDwarfFileDirective(
2477 0, File->getDirectory(), File->getFilename(), std::nullopt, std::nullopt,
2478 CUID);
2479
2480 auto *NVDD = static_cast<NVPTXDwarfDebug *>(getDwarfDebug());
2481 InlineAsmInliningContext InlineCtx =
2482 getInlineAsmInliningContext(DL, *MI->getMF(), NVDD, *OutStreamer, CUID);
2483
2484 SmallVector<StringRef, 16> Lines;
2485 Str.split(Lines, '\n');
2487 for (const StringRef &L : Lines) {
2488 StringRef RTrimmed = L.rtrim('\r');
2489 if (isPTXInstruction(L)) {
2490 if (InlineCtx.hasInlinedAt()) {
2491 OutStreamer->emitDwarfLocDirectiveWithInlinedAt(
2492 FileNumber, Line, Column, InlineCtx.FileIA, InlineCtx.LineIA,
2493 InlineCtx.ColIA, InlineCtx.FuncNameSym, DWARF2_FLAG_IS_STMT, 0, 0,
2494 File->getFilename());
2495 } else {
2496 OutStreamer->emitDwarfLocDirective(FileNumber, Line, Column,
2497 DWARF2_FLAG_IS_STMT, 0, 0,
2498 File->getFilename());
2499 }
2500 }
2501 OutStreamer->emitRawText(RTrimmed);
2502 ++Line;
2503 }
2504 emitInlineAsmEnd(STI, nullptr, MI);
2505}
2506
2507char NVPTXAsmPrinter::ID = 0;
2508
2509INITIALIZE_PASS(NVPTXAsmPrinter, "nvptx-asm-printer", "NVPTX Assembly Printer",
2510 false, false)
2511
2512// Force static initialization.
2513extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
2514LLVMInitializeNVPTXAsmPrinter() {
2517}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
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 & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
Hexagon Common GEP
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define DWARF2_FLAG_IS_STMT
Definition MCDwarf.h:119
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
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,...
#define DEPOTNAME
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 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.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
This file contains some templates that are useful if you are working with the STL at all.
static const char * name
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.
This file contains some functions that are useful when dealing with strings.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Value * RHS
Value * LHS
@ __CLK_ADDRESS_BASE
@ __CLK_FILTER_BASE
@ __CLK_NORMALIZED_BASE
@ __CLK_NORMALIZED_MASK
@ __CLK_ADDRESS_MASK
@ __CLK_FILTER_MASK
static const fltSemantics & IEEEsingle()
Definition APFloat.h:297
static const fltSemantics & IEEEdouble()
Definition APFloat.h:298
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:345
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:5920
APInt bitcastToAPInt() const
Definition APFloat.h:1457
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
Definition APInt.cpp:521
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
DwarfDebug * getDwarfDebug()
Definition AsmPrinter.h:290
virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo, const MachineInstr *MI)
Let the target do anything it needs to do after emitting inlineasm.
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
bool hasDebugInfo() const
Returns true if valid debug info is present.
Definition AsmPrinter.h:515
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
Definition AsmPrinter.h:622
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
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.
Definition AsmPrinter.h:453
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
virtual void emitFunctionBodyEnd()
Targets can override this to emit stuff after the last basic block in the function.
Definition AsmPrinter.h:626
const DataLayout & getDataLayout() const
Return information about data layout.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual void emitInlineAsmStart() const
Let the target do anything it needs to do before emitting inlineasm.
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)
const APFloat & getValueAPF() const
Definition Constants.h:463
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
FixedVectorType * getType() const
Specialize the getType() method to always return a FixedVectorType, which reduces the amount of casti...
Definition Constants.h:697
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition Constant.h:64
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
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)
Definition DenseMap.h:223
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:134
iterator end()
Definition DenseMap.h:141
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Collects and handles dwarf debug information.
Definition DwarfDebug.h:352
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
Definition Globals.cpp:730
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...
Definition Globals.cpp:408
bool hasLocalLinkage() const
bool hasPrivateLinkage() const
unsigned getAddressSpace() const
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.
Definition Type.cpp:348
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())
Definition MCExpr.h:342
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
Definition MCStreamer.h:385
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.
Definition MCStreamer.h:889
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
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...
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
int64_t getImm() 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.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
bool runOnMachineFunction(MachineFunction &F) override
Emit the specified function out to the OutStreamer.
DwarfDebug * createDwarfDebug() override
Create NVPTX-specific DwarfDebug handler.
std::string getVirtualRegisterName(unsigned) const
bool doFinalization(Module &M) override
Shut down the asmprinter.
const MCSymbol * getFunctionFrameSymbol() const override
Return symbol for the function pseudo stack if the stack frame is not a register based.
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)
Definition NVPTXMCExpr.h:44
static const NVPTXFloatMCExpr * createConstantFPHalf(const APFloat &Flt, MCContext &Ctx)
Definition NVPTXMCExpr.h:49
static const NVPTXFloatMCExpr * createConstantFPSingle(const APFloat &Flt, MCContext &Ctx)
Definition NVPTXMCExpr.h:54
static const NVPTXFloatMCExpr * createConstantFPDouble(const APFloat &Flt, MCContext &Ctx)
Definition NVPTXMCExpr.h:59
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.
const char * getName(unsigned RegNo) const
std::string getTargetName() const
unsigned getMaxRequiredAlignment() const
bool hasMaskOperator() const
const NVPTXTargetLowering * getTargetLowering() const override
unsigned getPTXVersion() const
const NVPTXRegisterInfo * getRegisterInfo() const override
unsigned int getSmVersion() const
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.
void outputDwarfFileDirectives()
Outputs the list of the DWARF '.file' directives to the streamer.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:66
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
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
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
iterator begin() const
Definition StringRef.h:114
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition StringRef.h:826
iterator end() const
Definition StringRef.h:116
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
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.
Definition Type.cpp:180
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
@ ArrayTyID
Arrays.
Definition Type.h:76
@ HalfTyID
16-bit floating point type
Definition Type.h:57
@ FloatTyID
32-bit floating point type
Definition Type.h:59
@ StructTyID
Structures.
Definition Type.h:75
@ IntegerTyID
Arbitrary bit width integers.
Definition Type.h:71
@ FixedVectorTyID
Fixed width SIMD vector type.
Definition Type.h:77
@ BFloatTyID
16-bit floating point type (7-bit significand)
Definition Type.h:58
@ DoubleTyID
64-bit floating point type
Definition Type.h:60
@ PointerTyID
Pointers.
Definition Type.h:74
@ FP128TyID
128-bit floating point type (112-bit significand)
Definition Type.h:62
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
Definition Type.h:270
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
TypeID getTypeID() const
Return the type id for the type.
Definition Type.h:138
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
op_range operands()
Definition User.h:267
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
iterator_range< user_iterator > users()
Definition Value.h:426
bool use_empty() const
Definition Value.h:346
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
void insert_range(Range &&R)
Definition DenseSet.h:235
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
Definition SCCIterator.h:48
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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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)
Definition MCAsmInfo.h:50
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
@ Ready
Emitted to memory, but waiting on transitive dependencies.
Definition Core.h:571
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
uint64_t read64le(const void *P)
Definition Endian.h:435
uint32_t read32le(const void *P)
Definition Endian.h:432
This is an optimization pass for GlobalISel generic memory operations.
bool isManaged(const Value &)
SmallVector< unsigned, 3 > getReqNTID(const Function &)
@ Offset
Definition DWP.cpp:578
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...
Definition STLExtras.h:2180
bool shouldEmitPTXNoReturn(const Value *V, const TargetMachine &TM)
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.
Definition STLExtras.h:1739
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.
Definition STLExtras.h:1669
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,...
Definition STLExtras.h:2554
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...
Definition STLExtras.h:2275
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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)
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2173
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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)
Definition Casting.h:753
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
unsigned promoteScalarArgumentSize(unsigned size)
SmallVector< unsigned, 3 > getMaxNTID(const Function &)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool shouldPassAsArray(Type *Ty)
StringRef getNVPTXRegClassStr(const TargetRegisterClass *RC)
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...
Definition STLExtras.h:551
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.
Definition Format.h:169
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...
Definition Casting.h:547
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
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()
bool isKernelFunction(const Function &F)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
StringRef getNVPTXRegClassName(const TargetRegisterClass *RC)
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.
Target & getTheNVPTXTarget32()
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
#define N
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
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,...