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