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 == "pzo") {
102 // PZO flag
104 O << ".pzo";
105 return;
106 } else if (Modifier == "relu") {
107 // RELU flag
109 O << ".relu";
110 return;
111 } else if (Modifier == "base") {
112 // Default operand
114 default:
115 return;
117 return;
119 O << ".rni";
120 return;
122 O << ".rzi";
123 return;
125 O << ".rmi";
126 return;
128 O << ".rpi";
129 return;
131 O << ".rn";
132 return;
134 O << ".rz";
135 return;
137 O << ".rm";
138 return;
140 O << ".rp";
141 return;
143 O << ".rna";
144 return;
146 O << ".rs";
147 return;
148 }
149 }
150 llvm_unreachable("Invalid conversion modifier");
151}
152
154 const MCSubtargetInfo &, raw_ostream &O) {
155 const MCOperand &MO = MI->getOperand(OpNum);
156 const int Imm = MO.getImm();
157 if (Imm)
158 O << ".ftz";
159}
160
162 const MCSubtargetInfo &, raw_ostream &O) {
163 const MCOperand &MO = MI->getOperand(OpNum);
164 if (MO.getImm())
165 O << "multimem.";
166}
167
169 const MCSubtargetInfo &,
170 raw_ostream &O) {
171 if (MI->getOperand(OpNum).getImm())
172 O << "!";
173}
174
176 const MCSubtargetInfo &, raw_ostream &O,
177 StringRef Modifier) {
178 const MCOperand &MO = MI->getOperand(OpNum);
179 int64_t Imm = MO.getImm();
180
181 if (Modifier == "FCmp") {
182 switch (Imm) {
183 default:
184 return;
186 O << "eq";
187 return;
189 O << "ne";
190 return;
192 O << "lt";
193 return;
195 O << "le";
196 return;
198 O << "gt";
199 return;
201 O << "ge";
202 return;
204 O << "equ";
205 return;
207 O << "neu";
208 return;
210 O << "ltu";
211 return;
213 O << "leu";
214 return;
216 O << "gtu";
217 return;
219 O << "geu";
220 return;
222 O << "num";
223 return;
225 O << "nan";
226 return;
227 }
228 }
229 if (Modifier == "ICmp") {
230 switch (Imm) {
231 default:
232 llvm_unreachable("Invalid ICmp mode");
234 O << "eq";
235 return;
237 O << "ne";
238 return;
241 O << "lt";
242 return;
245 O << "le";
246 return;
249 O << "gt";
250 return;
253 O << "ge";
254 return;
255 }
256 }
257 if (Modifier == "IType") {
258 switch (Imm) {
259 default:
260 llvm_unreachable("Invalid IType");
263 O << "b";
264 return;
269 O << "s";
270 return;
275 O << "u";
276 return;
277 }
278 }
279 llvm_unreachable("Empty Modifier");
280}
281
283 const MCSubtargetInfo &STI,
284 raw_ostream &O, StringRef Modifier) {
285 const MCOperand &MO = MI->getOperand(OpNum);
286 int Imm = (int)MO.getImm();
287 if (Modifier == "sem") {
288 auto Ordering = NVPTX::Ordering(Imm);
289 switch (Ordering) {
291 return;
293 O << ".relaxed";
294 return;
296 O << ".acquire";
297 return;
299 O << ".release";
300 return;
302 O << ".acq_rel";
303 return;
306 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
307 return;
309 O << ".volatile";
310 return;
312 O << ".mmio.relaxed";
313 return;
314 }
315 } else if (Modifier == "scope") {
316 auto S = NVPTX::Scope(Imm);
317 switch (S) {
320 return;
322 O << ".sys";
323 return;
325 O << ".cta";
326 return;
328 O << ".cluster";
329 return;
331 O << ".gpu";
332 return;
333 }
335 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
336 ScopeToString(S)));
337 } else if (Modifier == "addsp") {
338 auto A = NVPTX::AddressSpace(Imm);
339 switch (A) {
341 return;
349 O << "." << addressSpaceToString(A, hasParamSubqualifiers(STI));
350 return;
351 }
353 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
354 addressSpaceToString(A)));
355 } else if (Modifier == "sign") {
356 switch (Imm) {
358 O << "s";
359 return;
361 O << "u";
362 return;
364 O << "b";
365 return;
367 O << "f";
368 return;
369 default:
370 llvm_unreachable("Unknown register type");
371 }
372 }
373 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
374}
375
377 const MCSubtargetInfo &,
378 raw_ostream &O,
379 StringRef Modifier) {
380 const MCOperand &MO = MI->getOperand(OpNum);
381 unsigned Hint = MO.getImm();
382
383 // If no hint is set, print nothing.
384 if (Hint == 0)
385 return;
386
387 // Check if L2::cache_hint mode is active.
388 bool IsCacheHintMode = NVPTX::isL2CacheHintMode(Hint);
389
390 if (Modifier == "l1") {
391 switch (NVPTX::decodeL1Eviction(Hint)) {
393 return;
395 O << ".L1::evict_unchanged";
396 return;
398 O << ".L1::evict_first";
399 return;
401 O << ".L1::evict_last";
402 return;
404 O << ".L1::no_allocate";
405 return;
406 }
407 } else if (Modifier == "l2") {
408 switch (NVPTX::decodeL2Eviction(Hint)) {
410 break;
412 O << ".L2::evict_first";
413 break;
415 O << ".L2::evict_last";
416 break;
417 }
418 if (IsCacheHintMode)
419 O << ".L2::cache_hint";
420 return;
421 } else if (Modifier == "prefetch") {
422 switch (NVPTX::decodeL2Prefetch(Hint)) {
424 return;
426 O << ".L2::64B";
427 return;
429 O << ".L2::128B";
430 return;
432 O << ".L2::256B";
433 return;
434 }
435 }
436 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
437}
438
440 const MCSubtargetInfo &,
441 raw_ostream &O) {
442 const MCOperand &MO = MI->getOperand(OpNum);
443 // If the operand is a register and valid, print ", $reg"
444 if (MO.isReg() && MO.getReg().isValid()) {
445 O << ", ";
446 printRegName(O, MO.getReg());
447 }
448}
449
451 const MCSubtargetInfo &, raw_ostream &O,
452 StringRef Modifier) {
453 const MCOperand &MO = MI->getOperand(OpNum);
454 int Imm = (int)MO.getImm();
455 if (Modifier.empty() || Modifier == "version") {
456 O << Imm; // Just print out PTX version
457 return;
458 } else if (Modifier == "aligned") {
459 // PTX63 requires '.aligned' in the name of the instruction.
460 if (Imm >= 63)
461 O << ".aligned";
462 return;
463 }
464 llvm_unreachable("Unknown Modifier");
465}
466
468 const MCSubtargetInfo &STI,
469 raw_ostream &O, StringRef Modifier) {
470 printOperand(MI, OpNum, STI, O);
471
472 if (Modifier == "add") {
473 O << ", ";
474 printOperand(MI, OpNum + 1, STI, O);
475 } else {
476 if (MI->getOperand(OpNum + 1).isImm() &&
477 MI->getOperand(OpNum + 1).getImm() == 0)
478 return; // don't print ',0' or '+0'
479 O << "+";
480 printOperand(MI, OpNum + 1, STI, O);
481 }
482}
483
485 const MCSubtargetInfo &,
486 raw_ostream &O) {
487 auto &Op = MI->getOperand(OpNum);
488 assert(Op.isImm() && "Invalid operand");
489 uint32_t Imm = (uint32_t)Op.getImm();
490 if (Imm != UINT32_MAX) {
491 O << ".pragma \"used_bytes_mask " << format_hex(Imm, 1) << "\";\n\t";
492 }
493}
494
496 const MCSubtargetInfo &STI,
497 raw_ostream &O) {
498 const MCOperand &Op = MI->getOperand(OpNum);
499 if (Op.isReg() && Op.getReg() == MCRegister::NoRegister)
500 O << "_";
501 else
502 printOperand(MI, OpNum, STI, O);
503}
504
506 const MCSubtargetInfo &, raw_ostream &O) {
507 int64_t Imm = MI->getOperand(OpNum).getImm();
508 O << formatHex(Imm) << "U";
509}
510
512 const MCSubtargetInfo &, raw_ostream &O) {
513 const MCOperand &MO = MI->getOperand(OpNum);
514 int64_t Imm = MO.getImm();
515
516 switch (Imm) {
517 default:
518 return;
520 return;
522 O << ".f4e";
523 return;
525 O << ".b4e";
526 return;
528 O << ".rc8";
529 return;
531 O << ".ecl";
532 return;
534 O << ".ecr";
535 return;
537 O << ".rc16";
538 return;
539 }
540}
541
543 const MCSubtargetInfo &,
544 raw_ostream &O) {
545 const MCOperand &MO = MI->getOperand(OpNum);
546 O << '.'
548 static_cast<nvvm::TMAReductionOp>(MO.getImm()));
549}
550
552 const MCSubtargetInfo &, raw_ostream &O) {
553 const MCOperand &MO = MI->getOperand(OpNum);
554 using CGTy = nvvm::CTAGroupKind;
555
556 switch (static_cast<CGTy>(MO.getImm())) {
557 case CGTy::CG_NONE:
558 O << "";
559 return;
560 case CGTy::CG_1:
561 O << ".cta_group::1";
562 return;
563 case CGTy::CG_2:
564 O << ".cta_group::2";
565 return;
566 }
567 llvm_unreachable("Invalid cta_group in printCTAGroup");
568}
569
571 const MCSubtargetInfo &, raw_ostream &O,
572 StringRef Modifier) {
573 const auto Policy =
574 static_cast<nvvm::EvictPolicyType>(MI->getOperand(OpNum).getImm());
575 // Evict normal is the default priority policy for prefetch and does not print
576 // a qualifier.
578 return;
579 O << "." << nvvm::getEvictPolicyName(Policy);
580}
581
583 const MCSubtargetInfo &, raw_ostream &O,
584 StringRef Modifier) {
585 const MCOperand &MO = MI->getOperand(OpNum);
586 assert(MO.isImm() && "Invalid operand");
587 const auto Imm = MO.getImm();
588
589 if (Modifier == "RetList") {
590 assert((Imm == 1 || Imm == 0) && "Invalid return list");
591 if (Imm)
592 O << " (retval0),";
593 return;
594 }
595
596 if (Modifier == "ParamList") {
597 assert(Imm >= 0 && "Invalid parameter list");
599 [&](const auto &I) { O << "param" << I; });
600 return;
601 }
602 llvm_unreachable("Invalid modifier");
603}
604
605template <unsigned Bits>
607 const MCSubtargetInfo &, raw_ostream &O) {
608 const MCOperand &MO = MI->getOperand(OpNum);
609 assert(MO.isImm() && "Expected immediate operand");
610 assert(isInt<Bits>(MO.getImm()) &&
611 "Immediate value does not fit in specified bits");
612 uint64_t Imm = MO.getImm();
614 O << formatHex(Imm) << "U";
615}
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