LLVM 24.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
15#include "NVPTX.h"
16#include "NVPTXUtilities.h"
17#include "llvm/ADT/StringRef.h"
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/MC/MCSymbol.h"
27#include <cctype>
28using namespace llvm;
29
30#define DEBUG_TYPE "asm-printer"
31
32#define GET_SUBTARGETINFO_ENUM
33#include "NVPTXGenSubtargetInfo.inc"
34
35#include "NVPTXGenAsmWriter.inc"
36
37static bool hasParamSubqualifiers(const MCSubtargetInfo &STI) {
38 return STI.hasFeature(NVPTX::PTX83);
39}
40
44
46 // Decode a register packed by NVPTXAsmPrinter::encodeVirtualRegister.
47 const auto Kind = static_cast<NVPTX::VirtualRegisterKind>(
49
51 // This is actually a physical register, so defer to the autogenerated
52 // register printer
53 OS << getRegisterName(Reg);
54 return;
55 }
56
58 << (Reg.id() & NVPTX::VirtualRegisterNumMask);
59}
60
62 StringRef Annot, const MCSubtargetInfo &STI,
63 raw_ostream &OS) {
64 printInstruction(MI, Address, STI, OS);
65
66 // Next always print the annotation.
67 printAnnotation(OS, Annot);
68}
69
70void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
71 const MCSubtargetInfo &, raw_ostream &O) {
72 const MCOperand &Op = MI->getOperand(OpNo);
73 if (Op.isReg()) {
74 MCRegister Reg = Op.getReg();
75 printRegName(O, Reg);
76 } else if (Op.isImm()) {
77 markup(O, Markup::Immediate) << formatImm(Op.getImm());
78 } else {
79 assert(Op.isExpr() && "Unknown operand kind in printOperand");
80 MAI.printExpr(O, *Op.getExpr());
81 }
82}
83
85 const MCSubtargetInfo &, raw_ostream &O,
86 StringRef Modifier) {
87 const MCOperand &MO = MI->getOperand(OpNum);
88 int64_t Imm = MO.getImm();
89
90 if (Modifier == "ftz") {
91 // FTZ flag
93 O << ".ftz";
94 return;
95 } else if (Modifier == "sat") {
96 // SAT flag
98 O << ".sat";
99 return;
100 } else if (Modifier == "satfinite") {
101 // SATFINITE flag
103 O << ".satfinite";
104 return;
105 } else if (Modifier == "relu") {
106 // RELU flag
108 O << ".relu";
109 return;
110 } else if (Modifier == "base") {
111 // Default operand
112 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
113 default:
114 return;
116 return;
118 O << ".rni";
119 return;
121 O << ".rzi";
122 return;
124 O << ".rmi";
125 return;
127 O << ".rpi";
128 return;
130 O << ".rn";
131 return;
133 O << ".rz";
134 return;
136 O << ".rm";
137 return;
139 O << ".rp";
140 return;
142 O << ".rna";
143 return;
145 O << ".rs";
146 return;
147 }
148 }
149 llvm_unreachable("Invalid conversion modifier");
150}
151
153 const MCSubtargetInfo &, raw_ostream &O) {
154 const MCOperand &MO = MI->getOperand(OpNum);
155 const int Imm = MO.getImm();
156 if (Imm)
157 O << ".ftz";
158}
159
161 const MCSubtargetInfo &, raw_ostream &O) {
162 const MCOperand &MO = MI->getOperand(OpNum);
163 if (MO.getImm())
164 O << "multimem.";
165}
166
168 const MCSubtargetInfo &,
169 raw_ostream &O) {
170 if (MI->getOperand(OpNum).getImm())
171 O << "!";
172}
173
175 const MCSubtargetInfo &, raw_ostream &O,
176 StringRef Modifier) {
177 const MCOperand &MO = MI->getOperand(OpNum);
178 int64_t Imm = MO.getImm();
179
180 if (Modifier == "FCmp") {
181 switch (Imm) {
182 default:
183 return;
185 O << "eq";
186 return;
188 O << "ne";
189 return;
191 O << "lt";
192 return;
194 O << "le";
195 return;
197 O << "gt";
198 return;
200 O << "ge";
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 if (Modifier == "ICmp") {
229 switch (Imm) {
230 default:
231 llvm_unreachable("Invalid ICmp mode");
233 O << "eq";
234 return;
236 O << "ne";
237 return;
240 O << "lt";
241 return;
244 O << "le";
245 return;
248 O << "gt";
249 return;
252 O << "ge";
253 return;
254 }
255 }
256 if (Modifier == "IType") {
257 switch (Imm) {
258 default:
259 llvm_unreachable("Invalid IType");
262 O << "b";
263 return;
268 O << "s";
269 return;
274 O << "u";
275 return;
276 }
277 }
278 llvm_unreachable("Empty Modifier");
279}
280
282 const MCSubtargetInfo &STI,
283 raw_ostream &O, StringRef Modifier) {
284 const MCOperand &MO = MI->getOperand(OpNum);
285 int Imm = (int)MO.getImm();
286 if (Modifier == "sem") {
287 auto Ordering = NVPTX::Ordering(Imm);
288 switch (Ordering) {
290 return;
292 O << ".relaxed";
293 return;
295 O << ".acquire";
296 return;
298 O << ".release";
299 return;
301 O << ".acq_rel";
302 return;
305 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
306 return;
308 O << ".volatile";
309 return;
311 O << ".mmio.relaxed";
312 return;
313 }
314 } else if (Modifier == "scope") {
315 auto S = NVPTX::Scope(Imm);
316 switch (S) {
319 return;
321 O << ".sys";
322 return;
324 O << ".cta";
325 return;
327 O << ".cluster";
328 return;
330 O << ".gpu";
331 return;
332 }
334 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
335 ScopeToString(S)));
336 } else if (Modifier == "addsp") {
337 auto A = NVPTX::AddressSpace(Imm);
338 switch (A) {
340 return;
348 O << "." << addressSpaceToString(A, hasParamSubqualifiers(STI));
349 return;
350 }
352 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
353 addressSpaceToString(A)));
354 } else if (Modifier == "sign") {
355 switch (Imm) {
357 O << "s";
358 return;
360 O << "u";
361 return;
363 O << "b";
364 return;
366 O << "f";
367 return;
368 default:
369 llvm_unreachable("Unknown register type");
370 }
371 }
372 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
373}
374
376 const MCSubtargetInfo &, raw_ostream &O,
377 StringRef Modifier) {
378 const MCOperand &MO = MI->getOperand(OpNum);
379 int Imm = (int)MO.getImm();
380 if (Modifier.empty() || Modifier == "version") {
381 O << Imm; // Just print out PTX version
382 return;
383 } else if (Modifier == "aligned") {
384 // PTX63 requires '.aligned' in the name of the instruction.
385 if (Imm >= 63)
386 O << ".aligned";
387 return;
388 }
389 llvm_unreachable("Unknown Modifier");
390}
391
393 const MCSubtargetInfo &STI,
394 raw_ostream &O, StringRef Modifier) {
395 printOperand(MI, OpNum, STI, O);
396
397 if (Modifier == "add") {
398 O << ", ";
399 printOperand(MI, OpNum + 1, STI, O);
400 } else {
401 if (MI->getOperand(OpNum + 1).isImm() &&
402 MI->getOperand(OpNum + 1).getImm() == 0)
403 return; // don't print ',0' or '+0'
404 O << "+";
405 printOperand(MI, OpNum + 1, STI, O);
406 }
407}
408
410 const MCSubtargetInfo &,
411 raw_ostream &O) {
412 auto &Op = MI->getOperand(OpNum);
413 assert(Op.isImm() && "Invalid operand");
414 uint32_t Imm = (uint32_t)Op.getImm();
415 if (Imm != UINT32_MAX) {
416 O << ".pragma \"used_bytes_mask " << format_hex(Imm, 1) << "\";\n\t";
417 }
418}
419
421 const MCSubtargetInfo &STI,
422 raw_ostream &O) {
423 const MCOperand &Op = MI->getOperand(OpNum);
424 if (Op.isReg() && Op.getReg() == MCRegister::NoRegister)
425 O << "_";
426 else
427 printOperand(MI, OpNum, STI, O);
428}
429
431 const MCSubtargetInfo &, raw_ostream &O) {
432 int64_t Imm = MI->getOperand(OpNum).getImm();
433 O << formatHex(Imm) << "U";
434}
435
437 const MCSubtargetInfo &, raw_ostream &O) {
438 const MCOperand &MO = MI->getOperand(OpNum);
439 int64_t Imm = MO.getImm();
440
441 switch (Imm) {
442 default:
443 return;
445 return;
447 O << ".f4e";
448 return;
450 O << ".b4e";
451 return;
453 O << ".rc8";
454 return;
456 O << ".ecl";
457 return;
459 O << ".ecr";
460 return;
462 O << ".rc16";
463 return;
464 }
465}
466
468 const MCSubtargetInfo &,
469 raw_ostream &O) {
470 const MCOperand &MO = MI->getOperand(OpNum);
471 using RedTy = nvvm::TMAReductionOp;
472
473 switch (static_cast<RedTy>(MO.getImm())) {
474 case RedTy::ADD:
475 O << ".add";
476 return;
477 case RedTy::MIN:
478 O << ".min";
479 return;
480 case RedTy::MAX:
481 O << ".max";
482 return;
483 case RedTy::INC:
484 O << ".inc";
485 return;
486 case RedTy::DEC:
487 O << ".dec";
488 return;
489 case RedTy::AND:
490 O << ".and";
491 return;
492 case RedTy::OR:
493 O << ".or";
494 return;
495 case RedTy::XOR:
496 O << ".xor";
497 return;
498 }
500 "Invalid Reduction Op in printCpAsyncBulkTensorReductionMode");
501}
502
504 const MCSubtargetInfo &, raw_ostream &O) {
505 const MCOperand &MO = MI->getOperand(OpNum);
506 using CGTy = nvvm::CTAGroupKind;
507
508 switch (static_cast<CGTy>(MO.getImm())) {
509 case CGTy::CG_NONE:
510 O << "";
511 return;
512 case CGTy::CG_1:
513 O << ".cta_group::1";
514 return;
515 case CGTy::CG_2:
516 O << ".cta_group::2";
517 return;
518 }
519 llvm_unreachable("Invalid cta_group in printCTAGroup");
520}
521
523 const MCSubtargetInfo &, raw_ostream &O,
524 StringRef Modifier) {
525 const MCOperand &MO = MI->getOperand(OpNum);
526 assert(MO.isImm() && "Invalid operand");
527 const auto Imm = MO.getImm();
528
529 if (Modifier == "RetList") {
530 assert((Imm == 1 || Imm == 0) && "Invalid return list");
531 if (Imm)
532 O << " (retval0),";
533 return;
534 }
535
536 if (Modifier == "ParamList") {
537 assert(Imm >= 0 && "Invalid parameter list");
539 [&](const auto &I) { O << "param" << I; });
540 return;
541 }
542 llvm_unreachable("Invalid modifier");
543}
544
545template <unsigned Bits>
547 const MCSubtargetInfo &, raw_ostream &O) {
548 const MCOperand &MO = MI->getOperand(OpNum);
549 assert(MO.isImm() && "Expected immediate operand");
550 assert(isInt<Bits>(MO.getImm()) &&
551 "Immediate value does not fit in specified bits");
552 uint64_t Imm = MO.getImm();
553 Imm &= maskTrailingOnes<uint64_t>(Bits);
554 O << formatHex(Imm) << "U";
555}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
static bool hasParamSubqualifiers(const MCSubtargetInfo &STI)
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics,...
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:67
WithMarkup markup(raw_ostream &OS, Markup M)
format_object< int64_t > formatHex(int64_t Value) const
const MCInstrInfo & MII
const MCRegisterInfo & MRI
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
format_object< int64_t > formatImm(int64_t Value) const
Utility function to print immediates in decimal or hex.
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri)
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:41
static constexpr unsigned NoRegister
Definition MCRegister.h:60
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printMemOperand(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
void printAtomicCode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
void printInstruction(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O)
void printMmaCode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
void printTmaReductionMode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printMultimem(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printCallOperand(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
void printCmpMode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
static const char * getRegisterName(MCRegister Reg)
void printPrmtMode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printUsedBytesMaskPragma(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printRegisterOrSinkSymbol(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printHexu32imm(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printCvtMode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
void printFTZFlag(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, 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.
void printCTAGroup(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void printNegatedPredicate(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printHexUImm(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
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.
@ DeviceParam
Definition NVPTX.h:217
@ SharedCluster
Definition NVPTX.h:210
@ EntryParam
Definition NVPTX.h:211
@ DefaultDevice
Definition NVPTX.h:199
constexpr unsigned VirtualRegisterNumMask
@ RelaxedMMIO
Definition NVPTX.h:189
@ AcquireRelease
Definition NVPTX.h:185
@ NotAtomic
Definition NVPTX.h:178
@ SequentiallyConsistent
Definition NVPTX.h:186
constexpr unsigned VirtualRegisterKindShift
StringRef getVirtualRegisterPrefix(VirtualRegisterKind Kind)
The name prefix shared by all virtual registers of Kind.
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
Definition STLExtras.h:2313
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:163
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:156
DWARFExpression::Operation Op
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78