LLVM  14.0.0git
NVPTXAsmPrinter.h
Go to the documentation of this file.
1 //===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to NVPTX assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
15 #define LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
16 
17 #include "NVPTX.h"
18 #include "NVPTXSubtarget.h"
19 #include "NVPTXTargetMachine.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DebugLoc.h"
28 #include "llvm/IR/DerivedTypes.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/GlobalValue.h"
31 #include "llvm/IR/Value.h"
32 #include "llvm/MC/MCExpr.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/Pass.h"
36 #include "llvm/Support/Casting.h"
37 #include "llvm/Support/Compiler.h"
41 #include <algorithm>
42 #include <cassert>
43 #include <map>
44 #include <memory>
45 #include <string>
46 #include <vector>
47 
48 // The ptx syntax and format is very different from that usually seem in a .s
49 // file,
50 // therefore we are not able to use the MCAsmStreamer interface here.
51 //
52 // We are handcrafting the output method here.
53 //
54 // A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
55 // (subclass of MCStreamer).
56 
57 namespace llvm {
58 
59 class MCOperand;
60 
62 
63  class AggBuffer {
64  // Used to buffer the emitted string for initializing global
65  // aggregates.
66  //
67  // Normally an aggregate (array, vector or structure) is emitted
68  // as a u8[]. However, if one element/field of the aggregate
69  // is a non-NULL address, then the aggregate is emitted as u32[]
70  // or u64[].
71  //
72  // We first layout the aggregate in 'buffer' in bytes, except for
73  // those symbol addresses. For the i-th symbol address in the
74  //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
75  // are filled with 0s. symbolPosInBuffer[i-1] records its position
76  // in 'buffer', and Symbols[i-1] records the Value*.
77  //
78  // Once we have this AggBuffer setup, we can choose how to print
79  // it out.
80  public:
81  unsigned numSymbols; // number of symbol addresses
82 
83  private:
84  const unsigned size; // size of the buffer in bytes
85  std::vector<unsigned char> buffer; // the buffer
86  SmallVector<unsigned, 4> symbolPosInBuffer;
88  // SymbolsBeforeStripping[i] is the original form of Symbols[i] before
89  // stripping pointer casts, i.e.,
90  // Symbols[i] == SymbolsBeforeStripping[i]->stripPointerCasts().
91  //
92  // We need to keep these values because AggBuffer::print decides whether to
93  // emit a "generic()" cast for Symbols[i] depending on the address space of
94  // SymbolsBeforeStripping[i].
95  SmallVector<const Value *, 4> SymbolsBeforeStripping;
96  unsigned curpos;
97  raw_ostream &O;
98  NVPTXAsmPrinter &AP;
99  bool EmitGeneric;
100 
101  public:
102  AggBuffer(unsigned size, raw_ostream &O, NVPTXAsmPrinter &AP)
103  : size(size), buffer(size), O(O), AP(AP) {
104  curpos = 0;
105  numSymbols = 0;
106  EmitGeneric = AP.EmitGeneric;
107  }
108 
109  // Copy Num bytes from Ptr.
110  // if Bytes > Num, zero fill up to Bytes.
111  unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) {
112  assert((curpos + Num) <= size);
113  assert((curpos + Bytes) <= size);
114  for (int i = 0; i < Num; ++i) {
115  buffer[curpos] = Ptr[i];
116  curpos++;
117  }
118  for (int i = Num; i < Bytes; ++i) {
119  buffer[curpos] = 0;
120  curpos++;
121  }
122  return curpos;
123  }
124 
125  unsigned addZeros(int Num) {
126  assert((curpos + Num) <= size);
127  for (int i = 0; i < Num; ++i) {
128  buffer[curpos] = 0;
129  curpos++;
130  }
131  return curpos;
132  }
133 
134  void addSymbol(const Value *GVar, const Value *GVarBeforeStripping) {
135  symbolPosInBuffer.push_back(curpos);
136  Symbols.push_back(GVar);
137  SymbolsBeforeStripping.push_back(GVarBeforeStripping);
138  numSymbols++;
139  }
140 
141  void print() {
142  if (numSymbols == 0) {
143  // print out in bytes
144  for (unsigned i = 0; i < size; i++) {
145  if (i)
146  O << ", ";
147  O << (unsigned int) buffer[i];
148  }
149  } else {
150  // print out in 4-bytes or 8-bytes
151  unsigned int pos = 0;
152  unsigned int nSym = 0;
153  unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
154  unsigned int nBytes = 4;
155  if (static_cast<const NVPTXTargetMachine &>(AP.TM).is64Bit())
156  nBytes = 8;
157  for (pos = 0; pos < size; pos += nBytes) {
158  if (pos)
159  O << ", ";
160  if (pos == nextSymbolPos) {
161  const Value *v = Symbols[nSym];
162  const Value *v0 = SymbolsBeforeStripping[nSym];
163  if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
164  MCSymbol *Name = AP.getSymbol(GVar);
165  PointerType *PTy = dyn_cast<PointerType>(v0->getType());
166  bool IsNonGenericPointer = false; // Is v0 a non-generic pointer?
167  if (PTy && PTy->getAddressSpace() != 0) {
168  IsNonGenericPointer = true;
169  }
170  if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
171  O << "generic(";
172  Name->print(O, AP.MAI);
173  O << ")";
174  } else {
175  Name->print(O, AP.MAI);
176  }
177  } else if (const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(v0)) {
178  const MCExpr *Expr =
179  AP.lowerConstantForGV(cast<Constant>(CExpr), false);
180  AP.printMCExpr(*Expr, O);
181  } else
182  llvm_unreachable("symbol type unknown");
183  nSym++;
184  if (nSym >= numSymbols)
185  nextSymbolPos = size + 1;
186  else
187  nextSymbolPos = symbolPosInBuffer[nSym];
188  } else if (nBytes == 4)
189  O << *(unsigned int *)(&buffer[pos]);
190  else
191  O << *(unsigned long long *)(&buffer[pos]);
192  }
193  }
194  }
195  };
196 
197  friend class AggBuffer;
198 
199 private:
200  StringRef getPassName() const override { return "NVPTX Assembly Printer"; }
201 
202  const Function *F;
203  std::string CurrentFnName;
204 
205  void emitStartOfAsmFile(Module &M) override;
206  void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
207  void emitFunctionEntryLabel() override;
208  void emitFunctionBodyStart() override;
209  void emitFunctionBodyEnd() override;
210  void emitImplicitDef(const MachineInstr *MI) const override;
211 
212  void emitInstruction(const MachineInstr *) override;
213  void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
214  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
216  unsigned encodeVirtualRegister(unsigned Reg);
217 
218  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
219  const char *Modifier = nullptr);
220  void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O,
221  bool = false);
222  void printParamName(Function::const_arg_iterator I, int paramIndex,
223  raw_ostream &O);
224  void emitGlobals(const Module &M);
225  void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI);
226  void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const;
227  void emitVirtualRegister(unsigned int vr, raw_ostream &);
228  void emitFunctionParamList(const Function *, raw_ostream &O);
229  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
230  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
231  void printReturnValStr(const Function *, raw_ostream &O);
232  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
233  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
234  const char *ExtraCode, raw_ostream &) override;
235  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
236  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
237  const char *ExtraCode, raw_ostream &) override;
238 
239  const MCExpr *lowerConstantForGV(const Constant *CV, bool ProcessingGeneric);
240  void printMCExpr(const MCExpr &Expr, raw_ostream &OS);
241 
242 protected:
243  bool doInitialization(Module &M) override;
244  bool doFinalization(Module &M) override;
245 
246 private:
247  bool GlobalsEmitted;
248 
249  // This is specific per MachineFunction.
250  const MachineRegisterInfo *MRI;
251  // The contents are specific for each
252  // MachineFunction. But the size of the
253  // array is not.
254  typedef DenseMap<unsigned, unsigned> VRegMap;
256  VRegRCMap VRegMapping;
257 
258  // List of variables demoted to a function scope.
259  std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
260 
261  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
262  void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const;
263  std::string getPTXFundamentalTypeStr(Type *Ty, bool = true) const;
264  void printScalarConstant(const Constant *CPV, raw_ostream &O);
265  void printFPConstant(const ConstantFP *Fp, raw_ostream &O);
266  void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer);
267  void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer);
268 
269  void emitLinkageDirective(const GlobalValue *V, raw_ostream &O);
270  void emitDeclarations(const Module &, raw_ostream &O);
271  void emitDeclaration(const Function *, raw_ostream &O);
272  void emitDemotedVars(const Function *, raw_ostream &);
273 
274  bool lowerImageHandleOperand(const MachineInstr *MI, unsigned OpNo,
275  MCOperand &MCOp);
276  void lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp);
277 
278  bool isLoopHeaderOfNoUnroll(const MachineBasicBlock &MBB) const;
279 
280  // Used to control the need to emit .generic() in the initializer of
281  // module scope variables.
282  // Although ptx supports the hybrid mode like the following,
283  // .global .u32 a;
284  // .global .u32 b;
285  // .global .u32 addr[] = {a, generic(b)}
286  // we have difficulty representing the difference in the NVVM IR.
287  //
288  // Since the address value should always be generic in CUDA C and always
289  // be specific in OpenCL, we use this simple control here.
290  //
291  bool EmitGeneric;
292 
293 public:
294  NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
295  : AsmPrinter(TM, std::move(Streamer)),
296  EmitGeneric(static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() ==
297  NVPTX::CUDA) {}
298 
299  bool runOnMachineFunction(MachineFunction &F) override;
300 
301  void getAnalysisUsage(AnalysisUsage &AU) const override {
304  }
305 
306  std::string getVirtualRegisterName(unsigned) const;
307 
308  const MCSymbol *getFunctionFrameSymbol() const override;
309 
310  // Make emitGlobalVariable() no-op for NVPTX.
311  // Global variables have been already emitted by the time the base AsmPrinter
312  // attempts to do so in doFinalization() (see NVPTXAsmPrinter::emitGlobals()).
313  void emitGlobalVariable(const GlobalVariable *GV) override {}
314 };
315 
316 } // end namespace llvm
317 
318 #endif // LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
i
i
Definition: README.txt:29
AsmPrinter.h
llvm::Argument
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1558
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::NVPTXAsmPrinter::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Definition: NVPTXAsmPrinter.h:301
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:52
llvm::Function
Definition: Function.h:62
StringRef.h
Pass.h
llvm::NVPTXTargetMachine::is64Bit
bool is64Bit() const
Definition: NVPTXTargetMachine.h:47
llvm::AsmPrinter::MAI
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:87
llvm::SmallVector< unsigned, 4 >
ErrorHandling.h
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::PointerType::getAddressSpace
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:687
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
DenseMap.h
printOperand
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
Definition: SelectionDAGDumper.cpp:946
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::NVPTXTargetMachine
NVPTXTargetMachine.
Definition: NVPTXTargetMachine.h:25
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::MachineLoopInfo
Definition: MachineLoopInfo.h:90
NVPTX.h
printMCExpr
static void printMCExpr(const MCExpr *E, raw_ostream &OS)
Definition: SystemZAsmParser.cpp:702
GlobalValue.h
MachineLoopInfo.h
TargetMachine.h
Constants.h
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
MCSymbol.h
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::ConstantFP
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:257
DebugLoc.h
llvm::AddressSpace
AddressSpace
Definition: NVPTXBaseInfo.h:21
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::NVPTXSubtarget
Definition: NVPTXSubtarget.h:31
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:206
llvm::GlobalValue
Definition: GlobalValue.h:44
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::DenseMap< unsigned, unsigned >
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
printMemOperand
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
Definition: SelectionDAGDumper.cpp:513
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::AsmPrinter::getSymbol
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:485
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:80
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1658
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::MachineFunction
Definition: MachineFunction.h:234
llvm::size
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:1581
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::AsmPrinter::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Definition: AsmPrinter.cpp:259
GetSymbolRef
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, HexagonAsmPrinter &Printer, bool MustExtend)
Definition: HexagonMCInstLower.cpp:41
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
Compiler.h
llvm::NVPTXAsmPrinter
Definition: NVPTXAsmPrinter.h:61
LLVM_LIBRARY_VISIBILITY
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library,...
Definition: Compiler.h:131
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::NVPTXAsmPrinter::NVPTXAsmPrinter
NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
Definition: NVPTXAsmPrinter.h:294
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:936
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::NVPTX::CUDA
@ CUDA
Definition: NVPTX.h:72
Casting.h
NVPTXTargetMachine.h
Function.h
llvm::NVPTXAsmPrinter::emitGlobalVariable
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
Definition: NVPTXAsmPrinter.h:313
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:81
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
llvm::AsmPrinter::TM
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:84
SmallVector.h
MCStreamer.h
NVPTXSubtarget.h
DerivedTypes.h
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
raw_ostream.h
MachineFunction.h
Value.h
MCExpr.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35