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"
27using namespace llvm;
28
29#define DEBUG_TYPE "asm-printer"
30
31#include "NVPTXGenAsmWriter.inc"
32
33static bool hasParamSubqualifiers(const MCSubtargetInfo &STI) {
34 return STI.hasFeature(NVPTX::PTX83);
35}
36
40
42 // Decode a register packed by NVPTXAsmPrinter::encodeVirtualRegister.
43 const auto Kind = static_cast<NVPTX::VirtualRegisterKind>(
45
47 // This is actually a physical register, so defer to the autogenerated
48 // register printer
49 OS << getRegisterName(Reg);
50 return;
51 }
52
54 << (Reg.id() & NVPTX::VirtualRegisterNumMask);
55}
56
58 StringRef Annot, const MCSubtargetInfo &STI,
59 raw_ostream &OS) {
60 printInstruction(MI, Address, STI, OS);
61
62 // Next always print the annotation.
63 printAnnotation(OS, Annot);
64}
65
66void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
67 const MCSubtargetInfo &, raw_ostream &O) {
68 const MCOperand &Op = MI->getOperand(OpNo);
69 if (Op.isReg()) {
70 MCRegister Reg = Op.getReg();
71 printRegName(O, Reg);
72 } else if (Op.isImm()) {
73 markup(O, Markup::Immediate) << formatImm(Op.getImm());
74 } else {
75 assert(Op.isExpr() && "Unknown operand kind in printOperand");
76 MAI.printExpr(O, *Op.getExpr());
77 }
78}
79
81 const MCSubtargetInfo &, raw_ostream &O,
82 StringRef Modifier) {
83 const MCOperand &MO = MI->getOperand(OpNum);
84 int64_t Imm = MO.getImm();
85
86 if (Modifier == "ftz") {
87 // FTZ flag
89 O << ".ftz";
90 return;
91 } else if (Modifier == "sat") {
92 // SAT flag
94 O << ".sat";
95 return;
96 } else if (Modifier == "satfinite") {
97 // SATFINITE flag
99 O << ".satfinite";
100 return;
101 } else if (Modifier == "relu") {
102 // RELU flag
104 O << ".relu";
105 return;
106 } else if (Modifier == "base") {
107 // Default operand
109 default:
110 return;
112 return;
114 O << ".rni";
115 return;
117 O << ".rzi";
118 return;
120 O << ".rmi";
121 return;
123 O << ".rpi";
124 return;
126 O << ".rn";
127 return;
129 O << ".rz";
130 return;
132 O << ".rm";
133 return;
135 O << ".rp";
136 return;
138 O << ".rna";
139 return;
141 O << ".rs";
142 return;
143 }
144 }
145 llvm_unreachable("Invalid conversion modifier");
146}
147
149 const MCSubtargetInfo &, raw_ostream &O) {
150 const MCOperand &MO = MI->getOperand(OpNum);
151 const int Imm = MO.getImm();
152 if (Imm)
153 O << ".ftz";
154}
155
157 const MCSubtargetInfo &, raw_ostream &O) {
158 const MCOperand &MO = MI->getOperand(OpNum);
159 if (MO.getImm())
160 O << "multimem.";
161}
162
164 const MCSubtargetInfo &,
165 raw_ostream &O) {
166 if (MI->getOperand(OpNum).getImm())
167 O << "!";
168}
169
171 const MCSubtargetInfo &, raw_ostream &O,
172 StringRef Modifier) {
173 const MCOperand &MO = MI->getOperand(OpNum);
174 int64_t Imm = MO.getImm();
175
176 if (Modifier == "FCmp") {
177 switch (Imm) {
178 default:
179 return;
181 O << "eq";
182 return;
184 O << "ne";
185 return;
187 O << "lt";
188 return;
190 O << "le";
191 return;
193 O << "gt";
194 return;
196 O << "ge";
197 return;
199 O << "equ";
200 return;
202 O << "neu";
203 return;
205 O << "ltu";
206 return;
208 O << "leu";
209 return;
211 O << "gtu";
212 return;
214 O << "geu";
215 return;
217 O << "num";
218 return;
220 O << "nan";
221 return;
222 }
223 }
224 if (Modifier == "ICmp") {
225 switch (Imm) {
226 default:
227 llvm_unreachable("Invalid ICmp mode");
229 O << "eq";
230 return;
232 O << "ne";
233 return;
236 O << "lt";
237 return;
240 O << "le";
241 return;
244 O << "gt";
245 return;
248 O << "ge";
249 return;
250 }
251 }
252 if (Modifier == "IType") {
253 switch (Imm) {
254 default:
255 llvm_unreachable("Invalid IType");
258 O << "b";
259 return;
264 O << "s";
265 return;
270 O << "u";
271 return;
272 }
273 }
274 llvm_unreachable("Empty Modifier");
275}
276
278 const MCSubtargetInfo &STI,
279 raw_ostream &O, StringRef Modifier) {
280 const MCOperand &MO = MI->getOperand(OpNum);
281 int Imm = (int)MO.getImm();
282 if (Modifier == "sem") {
283 auto Ordering = NVPTX::Ordering(Imm);
284 switch (Ordering) {
286 return;
288 O << ".relaxed";
289 return;
291 O << ".acquire";
292 return;
294 O << ".release";
295 return;
297 O << ".acq_rel";
298 return;
301 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
302 return;
304 O << ".volatile";
305 return;
307 O << ".mmio.relaxed";
308 return;
309 }
310 } else if (Modifier == "scope") {
311 auto S = NVPTX::Scope(Imm);
312 switch (S) {
315 return;
317 O << ".sys";
318 return;
320 O << ".cta";
321 return;
323 O << ".cluster";
324 return;
326 O << ".gpu";
327 return;
328 }
330 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
331 ScopeToString(S)));
332 } else if (Modifier == "addsp") {
333 auto A = NVPTX::AddressSpace(Imm);
334 switch (A) {
336 return;
344 O << "." << addressSpaceToString(A, hasParamSubqualifiers(STI));
345 return;
346 }
348 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
349 addressSpaceToString(A)));
350 } else if (Modifier == "sign") {
351 switch (Imm) {
353 O << "s";
354 return;
356 O << "u";
357 return;
359 O << "b";
360 return;
362 O << "f";
363 return;
364 default:
365 llvm_unreachable("Unknown register type");
366 }
367 }
368 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
369}
370
372 const MCSubtargetInfo &,
373 raw_ostream &O,
374 StringRef Modifier) {
375 const MCOperand &MO = MI->getOperand(OpNum);
376 unsigned Hint = MO.getImm();
377
378 // If no hint is set, print nothing.
379 if (Hint == 0)
380 return;
381
382 // Check if L2::cache_hint mode is active.
383 bool IsCacheHintMode = NVPTX::isL2CacheHintMode(Hint);
384
385 if (Modifier == "l1") {
386 switch (NVPTX::decodeL1Eviction(Hint)) {
388 return;
390 O << ".L1::evict_unchanged";
391 return;
393 O << ".L1::evict_first";
394 return;
396 O << ".L1::evict_last";
397 return;
399 O << ".L1::no_allocate";
400 return;
401 }
402 } else if (Modifier == "l2") {
403 switch (NVPTX::decodeL2Eviction(Hint)) {
405 break;
407 O << ".L2::evict_first";
408 break;
410 O << ".L2::evict_last";
411 break;
412 }
413 if (IsCacheHintMode)
414 O << ".L2::cache_hint";
415 return;
416 } else if (Modifier == "prefetch") {
417 switch (NVPTX::decodeL2Prefetch(Hint)) {
419 return;
421 O << ".L2::64B";
422 return;
424 O << ".L2::128B";
425 return;
427 O << ".L2::256B";
428 return;
429 }
430 }
431 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
432}
433
435 const MCSubtargetInfo &,
436 raw_ostream &O) {
437 const MCOperand &MO = MI->getOperand(OpNum);
438 // If the operand is a register and valid, print ", $reg"
439 if (MO.isReg() && MO.getReg().isValid()) {
440 O << ", ";
441 printRegName(O, MO.getReg());
442 }
443}
444
446 const MCSubtargetInfo &, raw_ostream &O,
447 StringRef Modifier) {
448 const MCOperand &MO = MI->getOperand(OpNum);
449 int Imm = (int)MO.getImm();
450 if (Modifier.empty() || Modifier == "version") {
451 O << Imm; // Just print out PTX version
452 return;
453 } else if (Modifier == "aligned") {
454 // PTX63 requires '.aligned' in the name of the instruction.
455 if (Imm >= 63)
456 O << ".aligned";
457 return;
458 }
459 llvm_unreachable("Unknown Modifier");
460}
461
463 const MCSubtargetInfo &STI,
464 raw_ostream &O, StringRef Modifier) {
465 printOperand(MI, OpNum, STI, O);
466
467 if (Modifier == "add") {
468 O << ", ";
469 printOperand(MI, OpNum + 1, STI, O);
470 } else {
471 if (MI->getOperand(OpNum + 1).isImm() &&
472 MI->getOperand(OpNum + 1).getImm() == 0)
473 return; // don't print ',0' or '+0'
474 O << "+";
475 printOperand(MI, OpNum + 1, STI, O);
476 }
477}
478
480 const MCSubtargetInfo &,
481 raw_ostream &O) {
482 auto &Op = MI->getOperand(OpNum);
483 assert(Op.isImm() && "Invalid operand");
484 uint32_t Imm = (uint32_t)Op.getImm();
485 if (Imm != UINT32_MAX) {
486 O << ".pragma \"used_bytes_mask " << format_hex(Imm, 1) << "\";\n\t";
487 }
488}
489
491 const MCSubtargetInfo &STI,
492 raw_ostream &O) {
493 const MCOperand &Op = MI->getOperand(OpNum);
494 if (Op.isReg() && Op.getReg() == MCRegister::NoRegister)
495 O << "_";
496 else
497 printOperand(MI, OpNum, STI, O);
498}
499
501 const MCSubtargetInfo &, raw_ostream &O) {
502 int64_t Imm = MI->getOperand(OpNum).getImm();
503 O << formatHex(Imm) << "U";
504}
505
507 const MCSubtargetInfo &, raw_ostream &O) {
508 const MCOperand &MO = MI->getOperand(OpNum);
509 int64_t Imm = MO.getImm();
510
511 switch (Imm) {
512 default:
513 return;
515 return;
517 O << ".f4e";
518 return;
520 O << ".b4e";
521 return;
523 O << ".rc8";
524 return;
526 O << ".ecl";
527 return;
529 O << ".ecr";
530 return;
532 O << ".rc16";
533 return;
534 }
535}
536
538 const MCSubtargetInfo &,
539 raw_ostream &O) {
540 const MCOperand &MO = MI->getOperand(OpNum);
541 O << '.'
543 static_cast<nvvm::TMAReductionOp>(MO.getImm()));
544}
545
547 const MCSubtargetInfo &, raw_ostream &O) {
548 const MCOperand &MO = MI->getOperand(OpNum);
549 using CGTy = nvvm::CTAGroupKind;
550
551 switch (static_cast<CGTy>(MO.getImm())) {
552 case CGTy::CG_NONE:
553 O << "";
554 return;
555 case CGTy::CG_1:
556 O << ".cta_group::1";
557 return;
558 case CGTy::CG_2:
559 O << ".cta_group::2";
560 return;
561 }
562 llvm_unreachable("Invalid cta_group in printCTAGroup");
563}
564
566 const MCSubtargetInfo &, raw_ostream &O,
567 StringRef Modifier) {
568 const auto Policy =
569 static_cast<nvvm::EvictPolicyType>(MI->getOperand(OpNum).getImm());
570 // Evict normal is the default priority policy for prefetch and does not print
571 // a qualifier.
573 return;
574 O << "." << nvvm::getEvictPolicyName(Policy);
575}
576
578 const MCSubtargetInfo &, raw_ostream &O,
579 StringRef Modifier) {
580 const MCOperand &MO = MI->getOperand(OpNum);
581 assert(MO.isImm() && "Invalid operand");
582 const auto Imm = MO.getImm();
583
584 if (Modifier == "RetList") {
585 assert((Imm == 1 || Imm == 0) && "Invalid return list");
586 if (Imm)
587 O << " (retval0),";
588 return;
589 }
590
591 if (Modifier == "ParamList") {
592 assert(Imm >= 0 && "Invalid parameter list");
594 [&](const auto &I) { O << "param" << I; });
595 return;
596 }
597 llvm_unreachable("Invalid modifier");
598}
599
600template <unsigned Bits>
602 const MCSubtargetInfo &, raw_ostream &O) {
603 const MCOperand &MO = MI->getOperand(OpNum);
604 assert(MO.isImm() && "Expected immediate operand");
605 assert(isInt<Bits>(MO.getImm()) &&
606 "Immediate value does not fit in specified bits");
607 uint64_t Imm = MO.getImm();
609 O << formatHex(Imm) << "U";
610}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
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
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
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
constexpr bool isValid() const
Definition MCRegister.h:84
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 printCachePolicy(const MCInst *MI, int OpNum, 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 printEvictPolicy(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
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 printEvictionAndPrefetchHint(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef Modifier={})
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
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:334
@ SharedCluster
Definition NVPTX.h:327
@ EntryParam
Definition NVPTX.h:328
L2Prefetch decodeL2Prefetch(unsigned Hint)
Definition NVPTX.h:396
L1Eviction decodeL1Eviction(unsigned Hint)
Definition NVPTX.h:388
L2Eviction decodeL2Eviction(unsigned Hint)
Definition NVPTX.h:392
bool isL2CacheHintMode(unsigned Hint)
Definition NVPTX.h:400
@ DefaultDevice
Definition NVPTX.h:316
constexpr unsigned VirtualRegisterNumMask
@ RelaxedMMIO
Definition NVPTX.h:306
@ AcquireRelease
Definition NVPTX.h:302
@ NotAtomic
Definition NVPTX.h:295
@ SequentiallyConsistent
Definition NVPTX.h:303
constexpr unsigned VirtualRegisterKindShift
StringRef getVirtualRegisterPrefix(VirtualRegisterKind Kind)
The name prefix shared by all virtual registers of Kind.
StringRef getEvictPolicyName(EvictPolicyType Policy)
StringRef getTMATensorReductionOpName(TMAReductionOp Op)
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)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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:164
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