LLVM 22.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/MCAsmInfo.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCSymbol.h"
26#include <cctype>
27using namespace llvm;
28
29#define DEBUG_TYPE "asm-printer"
30
31#include "NVPTXGenAsmWriter.inc"
32
34 const MCRegisterInfo &MRI)
35 : MCInstPrinter(MAI, MII, MRI) {}
36
38 // Decode the virtual register
39 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
40 unsigned RCId = (Reg.id() >> 28);
41 switch (RCId) {
42 default: report_fatal_error("Bad virtual register encoding");
43 case 0:
44 // This is actually a physical register, so defer to the autogenerated
45 // register printer
46 OS << getRegisterName(Reg);
47 return;
48 case 1:
49 OS << "%p";
50 break;
51 case 2:
52 OS << "%rs";
53 break;
54 case 3:
55 OS << "%r";
56 break;
57 case 4:
58 OS << "%rd";
59 break;
60 case 5:
61 OS << "%f";
62 break;
63 case 6:
64 OS << "%fd";
65 break;
66 case 7:
67 OS << "%rq";
68 break;
69 }
70
71 unsigned VReg = Reg.id() & 0x0FFFFFFF;
72 OS << VReg;
73}
74
76 StringRef Annot, const MCSubtargetInfo &STI,
77 raw_ostream &OS) {
79
80 // Next always print the annotation.
81 printAnnotation(OS, Annot);
82}
83
84void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
85 raw_ostream &O) {
86 const MCOperand &Op = MI->getOperand(OpNo);
87 if (Op.isReg()) {
88 MCRegister Reg = Op.getReg();
89 printRegName(O, Reg);
90 } else if (Op.isImm()) {
91 markup(O, Markup::Immediate) << formatImm(Op.getImm());
92 } else {
93 assert(Op.isExpr() && "Unknown operand kind in printOperand");
94 MAI.printExpr(O, *Op.getExpr());
95 }
96}
97
99 StringRef Modifier) {
100 const MCOperand &MO = MI->getOperand(OpNum);
101 int64_t Imm = MO.getImm();
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 raw_ostream &O) {
159 const MCOperand &MO = MI->getOperand(OpNum);
160 const int Imm = MO.getImm();
161 if (Imm)
162 O << ".ftz";
163}
164
166 StringRef Modifier) {
167 const MCOperand &MO = MI->getOperand(OpNum);
168 int64_t Imm = MO.getImm();
169
170 if (Modifier == "FCmp") {
171 switch (Imm) {
172 default:
173 return;
175 O << "eq";
176 return;
178 O << "ne";
179 return;
181 O << "lt";
182 return;
184 O << "le";
185 return;
187 O << "gt";
188 return;
190 O << "ge";
191 return;
193 O << "equ";
194 return;
196 O << "neu";
197 return;
199 O << "ltu";
200 return;
202 O << "leu";
203 return;
205 O << "gtu";
206 return;
208 O << "geu";
209 return;
211 O << "num";
212 return;
214 O << "nan";
215 return;
216 }
217 }
218 if (Modifier == "ICmp") {
219 switch (Imm) {
220 default:
221 llvm_unreachable("Invalid ICmp mode");
223 O << "eq";
224 return;
226 O << "ne";
227 return;
230 O << "lt";
231 return;
234 O << "le";
235 return;
238 O << "gt";
239 return;
242 O << "ge";
243 return;
244 }
245 }
246 if (Modifier == "IType") {
247 switch (Imm) {
248 default:
249 llvm_unreachable("Invalid IType");
252 O << "b";
253 return;
258 O << "s";
259 return;
264 O << "u";
265 return;
266 }
267 }
268 llvm_unreachable("Empty Modifier");
269}
270
272 raw_ostream &O, StringRef Modifier) {
273 const MCOperand &MO = MI->getOperand(OpNum);
274 int Imm = (int)MO.getImm();
275 if (Modifier == "sem") {
276 auto Ordering = NVPTX::Ordering(Imm);
277 switch (Ordering) {
279 return;
281 O << ".relaxed";
282 return;
284 O << ".acquire";
285 return;
287 O << ".release";
288 return;
290 O << ".acq_rel";
291 return;
294 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
295 return;
297 O << ".volatile";
298 return;
300 O << ".mmio.relaxed";
301 return;
302 }
303 } else if (Modifier == "scope") {
304 auto S = NVPTX::Scope(Imm);
305 switch (S) {
308 return;
310 O << ".sys";
311 return;
313 O << ".cta";
314 return;
316 O << ".cluster";
317 return;
319 O << ".gpu";
320 return;
321 }
323 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
324 ScopeToString(S)));
325 } else if (Modifier == "addsp") {
326 auto A = NVPTX::AddressSpace(Imm);
327 switch (A) {
329 return;
336 O << "." << A;
337 return;
338 }
340 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
341 AddressSpaceToString(A)));
342 } else if (Modifier == "sign") {
343 switch (Imm) {
345 O << "s";
346 return;
348 O << "u";
349 return;
351 O << "b";
352 return;
354 O << "f";
355 return;
356 default:
357 llvm_unreachable("Unknown register type");
358 }
359 }
360 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
361}
362
364 StringRef Modifier) {
365 const MCOperand &MO = MI->getOperand(OpNum);
366 int Imm = (int)MO.getImm();
367 if (Modifier.empty() || Modifier == "version") {
368 O << Imm; // Just print out PTX version
369 return;
370 } else if (Modifier == "aligned") {
371 // PTX63 requires '.aligned' in the name of the instruction.
372 if (Imm >= 63)
373 O << ".aligned";
374 return;
375 }
376 llvm_unreachable("Unknown Modifier");
377}
378
380 raw_ostream &O, StringRef Modifier) {
381 printOperand(MI, OpNum, O);
382
383 if (Modifier == "add") {
384 O << ", ";
385 printOperand(MI, OpNum + 1, O);
386 } else {
387 if (MI->getOperand(OpNum + 1).isImm() &&
388 MI->getOperand(OpNum + 1).getImm() == 0)
389 return; // don't print ',0' or '+0'
390 O << "+";
391 printOperand(MI, OpNum + 1, O);
392 }
393}
394
396 raw_ostream &O) {
397 int64_t Imm = MI->getOperand(OpNum).getImm();
398 O << formatHex(Imm) << "U";
399}
400
402 raw_ostream &O) {
403 const MCOperand &Op = MI->getOperand(OpNum);
404 assert(Op.isExpr() && "Call prototype is not an MCExpr?");
405 const MCExpr *Expr = Op.getExpr();
406 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
407 O << Sym.getName();
408}
409
411 raw_ostream &O) {
412 const MCOperand &MO = MI->getOperand(OpNum);
413 int64_t Imm = MO.getImm();
414
415 switch (Imm) {
416 default:
417 return;
419 return;
421 O << ".f4e";
422 return;
424 O << ".b4e";
425 return;
427 O << ".rc8";
428 return;
430 O << ".ecl";
431 return;
433 O << ".ecr";
434 return;
436 O << ".rc16";
437 return;
438 }
439}
440
442 raw_ostream &O) {
443 const MCOperand &MO = MI->getOperand(OpNum);
444 using RedTy = nvvm::TMAReductionOp;
445
446 switch (static_cast<RedTy>(MO.getImm())) {
447 case RedTy::ADD:
448 O << ".add";
449 return;
450 case RedTy::MIN:
451 O << ".min";
452 return;
453 case RedTy::MAX:
454 O << ".max";
455 return;
456 case RedTy::INC:
457 O << ".inc";
458 return;
459 case RedTy::DEC:
460 O << ".dec";
461 return;
462 case RedTy::AND:
463 O << ".and";
464 return;
465 case RedTy::OR:
466 O << ".or";
467 return;
468 case RedTy::XOR:
469 O << ".xor";
470 return;
471 }
473 "Invalid Reduction Op in printCpAsyncBulkTensorReductionMode");
474}
475
477 raw_ostream &O) {
478 const MCOperand &MO = MI->getOperand(OpNum);
479 using CGTy = nvvm::CTAGroupKind;
480
481 switch (static_cast<CGTy>(MO.getImm())) {
482 case CGTy::CG_NONE:
483 O << "";
484 return;
485 case CGTy::CG_1:
486 O << ".cta_group::1";
487 return;
488 case CGTy::CG_2:
489 O << ".cta_group::2";
490 return;
491 }
492 llvm_unreachable("Invalid cta_group in printCTAGroup");
493}
494
496 raw_ostream &O, StringRef Modifier) {
497 const MCOperand &MO = MI->getOperand(OpNum);
498 assert(MO.isImm() && "Invalid operand");
499 const auto Imm = MO.getImm();
500
501 if (Modifier == "RetList") {
502 assert((Imm == 1 || Imm == 0) && "Invalid return list");
503 if (Imm)
504 O << " (retval0),";
505 return;
506 }
507
508 if (Modifier == "ParamList") {
509 assert(Imm >= 0 && "Invalid parameter list");
511 [&](const auto &I) { O << "param" << I; });
512 return;
513 }
514 llvm_unreachable("Invalid modifier");
515}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Symbol * Sym
Definition: ELF_riscv.cpp:479
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics,...
raw_pwrite_stream & OS
This class represents an Operation in the Expression.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:64
void printExpr(raw_ostream &, const MCExpr &) const
Definition: MCAsmInfo.cpp:153
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:188
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
int64_t getImm() const
Definition: MCInst.h:84
bool isImm() const
Definition: MCInst.h:66
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:42
void printFTZFlag(const MCInst *MI, int OpNum, raw_ostream &O)
void printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printHexu32imm(const MCInst *MI, int OpNum, raw_ostream &O)
void printCTAGroup(const MCInst *MI, int OpNum, raw_ostream &O)
void printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
void printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
void printProtoIdent(const MCInst *MI, int OpNum, raw_ostream &O)
void printAtomicCode(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
static const char * getRegisterName(MCRegister Reg)
void printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
void printTmaReductionMode(const MCInst *MI, int OpNum, raw_ostream &O)
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.
NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void printPrmtMode(const MCInst *MI, int OpNum, raw_ostream &O)
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printMemOperand(const MCInst *MI, int OpNum, raw_ostream &O, StringRef Modifier={})
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
AddressSpace
Definition: NVPTX.h:181
@ Global
Definition: NVPTX.h:183
@ SharedCluster
Definition: NVPTX.h:187
@ Shared
Definition: NVPTX.h:184
@ Generic
Definition: NVPTX.h:182
@ System
Definition: NVPTX.h:175
@ Cluster
Definition: NVPTX.h:173
@ Thread
Definition: NVPTX.h:171
@ Device
Definition: NVPTX.h:174
@ DefaultDevice
Definition: NVPTX.h:176
@ RelaxedMMIO
Definition: NVPTX.h:166
@ Acquire
Definition: NVPTX.h:160
@ Relaxed
Definition: NVPTX.h:158
@ AcquireRelease
Definition: NVPTX.h:162
@ NotAtomic
Definition: NVPTX.h:155
@ Volatile
Definition: NVPTX.h:165
@ Release
Definition: NVPTX.h:161
@ SequentiallyConsistent
Definition: NVPTX.h:163
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
Definition: STLExtras.h:2250
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition: Sequence.h:305