LLVM 20.0.0git
NVPTXInstPrinter.cpp
Go to the documentation of this file.
1//===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
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// Print MCInst instructions to .ptx format.
10//
11//===----------------------------------------------------------------------===//
12
14#include "NVPTX.h"
15#include "NVPTXUtilities.h"
16#include "llvm/ADT/StringRef.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCSymbol.h"
25#include <cctype>
26using namespace llvm;
27
28#define DEBUG_TYPE "asm-printer"
29
30#include "NVPTXGenAsmWriter.inc"
31
33 const MCRegisterInfo &MRI)
34 : MCInstPrinter(MAI, MII, MRI) {}
35
37 // Decode the virtual register
38 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
39 unsigned RCId = (Reg.id() >> 28);
40 switch (RCId) {
41 default: report_fatal_error("Bad virtual register encoding");
42 case 0:
43 // This is actually a physical register, so defer to the autogenerated
44 // register printer
45 OS << getRegisterName(Reg);
46 return;
47 case 1:
48 OS << "%p";
49 break;
50 case 2:
51 OS << "%rs";
52 break;
53 case 3:
54 OS << "%r";
55 break;
56 case 4:
57 OS << "%rd";
58 break;
59 case 5:
60 OS << "%f";
61 break;
62 case 6:
63 OS << "%fd";
64 break;
65 case 7:
66 OS << "%rq";
67 break;
68 }
69
70 unsigned VReg = Reg.id() & 0x0FFFFFFF;
71 OS << VReg;
72}
73
75 StringRef Annot, const MCSubtargetInfo &STI,
76 raw_ostream &OS) {
78
79 // Next always print the annotation.
80 printAnnotation(OS, Annot);
81}
82
83void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
84 raw_ostream &O) {
85 const MCOperand &Op = MI->getOperand(OpNo);
86 if (Op.isReg()) {
87 unsigned Reg = Op.getReg();
88 printRegName(O, Reg);
89 } else if (Op.isImm()) {
90 markup(O, Markup::Immediate) << formatImm(Op.getImm());
91 } else {
92 assert(Op.isExpr() && "Unknown operand kind in printOperand");
93 Op.getExpr()->print(O, &MAI);
94 }
95}
96
98 const char *M) {
99 const MCOperand &MO = MI->getOperand(OpNum);
100 int64_t Imm = MO.getImm();
101 llvm::StringRef Modifier(M);
102
103 if (Modifier == "ftz") {
104 // FTZ flag
106 O << ".ftz";
107 return;
108 } else if (Modifier == "sat") {
109 // SAT flag
111 O << ".sat";
112 return;
113 } else if (Modifier == "relu") {
114 // RELU flag
116 O << ".relu";
117 return;
118 } else if (Modifier == "base") {
119 // Default operand
120 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
121 default:
122 return;
124 return;
126 O << ".rni";
127 return;
129 O << ".rzi";
130 return;
132 O << ".rmi";
133 return;
135 O << ".rpi";
136 return;
138 O << ".rn";
139 return;
141 O << ".rz";
142 return;
144 O << ".rm";
145 return;
147 O << ".rp";
148 return;
150 O << ".rna";
151 return;
152 }
153 }
154 llvm_unreachable("Invalid conversion modifier");
155}
156
158 const char *M) {
159 const MCOperand &MO = MI->getOperand(OpNum);
160 int64_t Imm = MO.getImm();
161 llvm::StringRef Modifier(M);
162
163 if (Modifier == "ftz") {
164 // FTZ flag
166 O << ".ftz";
167 return;
168 } else if (Modifier == "base") {
169 switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
170 default:
171 return;
173 O << ".eq";
174 return;
176 O << ".ne";
177 return;
179 O << ".lt";
180 return;
182 O << ".le";
183 return;
185 O << ".gt";
186 return;
188 O << ".ge";
189 return;
191 O << ".lo";
192 return;
194 O << ".ls";
195 return;
197 O << ".hi";
198 return;
200 O << ".hs";
201 return;
203 O << ".equ";
204 return;
206 O << ".neu";
207 return;
209 O << ".ltu";
210 return;
212 O << ".leu";
213 return;
215 O << ".gtu";
216 return;
218 O << ".geu";
219 return;
221 O << ".num";
222 return;
224 O << ".nan";
225 return;
226 }
227 }
228 llvm_unreachable("Empty Modifier");
229}
230
232 raw_ostream &O, const char *M) {
233 llvm::StringRef Modifier(M);
234 const MCOperand &MO = MI->getOperand(OpNum);
235 int Imm = (int)MO.getImm();
236 if (Modifier == "sem") {
237 auto Ordering = NVPTX::Ordering(Imm);
238 switch (Ordering) {
240 return;
242 O << ".relaxed";
243 return;
245 O << ".acquire";
246 return;
248 O << ".release";
249 return;
251 O << ".volatile";
252 return;
254 O << ".mmio.relaxed";
255 return;
256 default:
258 "NVPTX LdStCode Printer does not support \"{}\" sem modifier. "
259 "Loads/Stores cannot be AcquireRelease or SequentiallyConsistent.",
260 OrderingToString(Ordering)));
261 }
262 } else if (Modifier == "scope") {
263 auto S = NVPTX::Scope(Imm);
264 switch (S) {
266 return;
268 O << ".sys";
269 return;
271 O << ".cta";
272 return;
274 O << ".cluster";
275 return;
277 O << ".gpu";
278 return;
279 }
281 formatv("NVPTX LdStCode Printer does not support \"{}\" sco modifier.",
282 ScopeToString(S)));
283 } else if (Modifier == "addsp") {
284 auto A = NVPTX::AddressSpace(Imm);
285 switch (A) {
287 return;
293 O << "." << A;
294 return;
295 }
297 "NVPTX LdStCode Printer does not support \"{}\" addsp modifier.",
298 AddressSpaceToString(A)));
299 } else if (Modifier == "sign") {
300 switch (Imm) {
302 O << "s";
303 return;
305 O << "u";
306 return;
308 O << "b";
309 return;
311 O << "f";
312 return;
313 default:
314 llvm_unreachable("Unknown register type");
315 }
316 } else if (Modifier == "vec") {
317 switch (Imm) {
319 O << ".v2";
320 return;
322 O << ".v4";
323 return;
324 }
325 // TODO: evaluate whether cases not covered by this switch are bugs
326 return;
327 }
328 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
329}
330
332 const char *M) {
333 const MCOperand &MO = MI->getOperand(OpNum);
334 int Imm = (int)MO.getImm();
335 llvm::StringRef Modifier(M);
336 if (Modifier.empty() || Modifier == "version") {
337 O << Imm; // Just print out PTX version
338 return;
339 } else if (Modifier == "aligned") {
340 // PTX63 requires '.aligned' in the name of the instruction.
341 if (Imm >= 63)
342 O << ".aligned";
343 return;
344 }
345 llvm_unreachable("Unknown Modifier");
346}
347
349 raw_ostream &O, const char *M) {
350 printOperand(MI, OpNum, O);
351 llvm::StringRef Modifier(M);
352
353 if (Modifier == "add") {
354 O << ", ";
355 printOperand(MI, OpNum + 1, O);
356 } else {
357 if (MI->getOperand(OpNum + 1).isImm() &&
358 MI->getOperand(OpNum + 1).getImm() == 0)
359 return; // don't print ',0' or '+0'
360 O << "+";
361 printOperand(MI, OpNum + 1, O);
362 }
363}
364
366 raw_ostream &O, const char *Modifier) {
367 auto &Op = MI->getOperand(OpNum);
368 assert(Op.isImm() && "Invalid operand");
369 if (Op.getImm() != 0) {
370 O << "+";
371 printOperand(MI, OpNum, O);
372 }
373}
374
376 raw_ostream &O, const char *Modifier) {
377 int64_t Imm = MI->getOperand(OpNum).getImm();
378 O << formatHex(Imm) << "U";
379}
380
382 raw_ostream &O, const char *Modifier) {
383 const MCOperand &Op = MI->getOperand(OpNum);
384 assert(Op.isExpr() && "Call prototype is not an MCExpr?");
385 const MCExpr *Expr = Op.getExpr();
386 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
387 O << Sym.getName();
388}
389
391 raw_ostream &O, const char *Modifier) {
392 const MCOperand &MO = MI->getOperand(OpNum);
393 int64_t Imm = MO.getImm();
394
395 switch (Imm) {
396 default:
397 return;
399 return;
401 O << ".f4e";
402 return;
404 O << ".b4e";
405 return;
407 O << ".rc8";
408 return;
410 O << ".ecl";
411 return;
413 O << ".ecr";
414 return;
416 O << ".rc16";
417 return;
418 }
419}
420
422 raw_ostream &O,
423 const char *Modifier) {
424 const MCOperand &MO = MI->getOperand(OpNum);
425 using RedTy = llvm::nvvm::TMAReductionOp;
426
427 switch (static_cast<RedTy>(MO.getImm())) {
428 case RedTy::ADD:
429 O << ".add";
430 return;
431 case RedTy::MIN:
432 O << ".min";
433 return;
434 case RedTy::MAX:
435 O << ".max";
436 return;
437 case RedTy::INC:
438 O << ".inc";
439 return;
440 case RedTy::DEC:
441 O << ".dec";
442 return;
443 case RedTy::AND:
444 O << ".and";
445 return;
446 case RedTy::OR:
447 O << ".or";
448 return;
449 case RedTy::XOR:
450 O << ".xor";
451 return;
452 }
454 "Invalid Reduction Op in printCpAsyncBulkTensorReductionMode");
455}
unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Symbol * Sym
Definition: ELF_riscv.cpp:479
IRTranslator LLVM IR MI
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This class represents an Operation in the Expression.
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:46
WithMarkup markup(raw_ostream &OS, Markup M)
format_object< int64_t > formatHex(int64_t Value) const
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:52
format_object< int64_t > formatImm(int64_t Value) const
Utility function to print immediates in decimal or hex.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
int64_t getImm() const
Definition: MCInst.h:81
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printHexu32imm(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printMemOperand(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printOffseti32imm(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
void printLdStCode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printTmaReductionMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printProtoIdent(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
static const char * getRegisterName(MCRegister Reg)
void printPrmtMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &OS) override
Print the specified MCInst to the specified raw_ostream.
void printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
AddressSpace
Definition: NVPTX.h:143
@ Global
Definition: NVPTX.h:145
@ Shared
Definition: NVPTX.h:146
@ Generic
Definition: NVPTX.h:144
@ System
Definition: NVPTX.h:138
@ Cluster
Definition: NVPTX.h:136
@ Thread
Definition: NVPTX.h:134
@ Device
Definition: NVPTX.h:137
@ RelaxedMMIO
Definition: NVPTX.h:128
@ Acquire
Definition: NVPTX.h:122
@ Relaxed
Definition: NVPTX.h:120
@ NotAtomic
Definition: NVPTX.h:117
@ Volatile
Definition: NVPTX.h:127
@ Release
Definition: NVPTX.h:123
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167