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 &,
155 raw_ostream &O) {
156 const auto RM =
157 static_cast<APFloat::roundingMode>(MI->getOperand(OpNum).getImm());
158 const StringRef Name = nvvm::GetRoundingModeName(RM);
159 assert(!Name.empty() && "Invalid FP rounding mode");
160 O << Name;
161}
162
164 const MCSubtargetInfo &, raw_ostream &O) {
165 const MCOperand &MO = MI->getOperand(OpNum);
166 const int Imm = MO.getImm();
167 if (Imm)
168 O << ".ftz";
169}
170
172 const MCSubtargetInfo &, raw_ostream &O) {
173 const MCOperand &MO = MI->getOperand(OpNum);
174 if (MO.getImm())
175 O << "multimem.";
176}
177
179 const MCSubtargetInfo &,
180 raw_ostream &O) {
181 if (MI->getOperand(OpNum).getImm())
182 O << "!";
183}
184
186 const MCSubtargetInfo &, raw_ostream &O,
187 StringRef Modifier) {
188 const MCOperand &MO = MI->getOperand(OpNum);
189 int64_t Imm = MO.getImm();
190
191 if (Modifier == "FCmp") {
192 switch (Imm) {
193 default:
194 return;
196 O << "eq";
197 return;
199 O << "ne";
200 return;
202 O << "lt";
203 return;
205 O << "le";
206 return;
208 O << "gt";
209 return;
211 O << "ge";
212 return;
214 O << "equ";
215 return;
217 O << "neu";
218 return;
220 O << "ltu";
221 return;
223 O << "leu";
224 return;
226 O << "gtu";
227 return;
229 O << "geu";
230 return;
232 O << "num";
233 return;
235 O << "nan";
236 return;
237 }
238 }
239 if (Modifier == "ICmp") {
240 switch (Imm) {
241 default:
242 llvm_unreachable("Invalid ICmp mode");
244 O << "eq";
245 return;
247 O << "ne";
248 return;
251 O << "lt";
252 return;
255 O << "le";
256 return;
259 O << "gt";
260 return;
263 O << "ge";
264 return;
265 }
266 }
267 if (Modifier == "IType") {
268 switch (Imm) {
269 default:
270 llvm_unreachable("Invalid IType");
273 O << "b";
274 return;
279 O << "s";
280 return;
285 O << "u";
286 return;
287 }
288 }
289 llvm_unreachable("Empty Modifier");
290}
291
293 const MCSubtargetInfo &STI,
294 raw_ostream &O, StringRef Modifier) {
295 const MCOperand &MO = MI->getOperand(OpNum);
296 int Imm = (int)MO.getImm();
297 if (Modifier == "sem") {
298 auto Ordering = NVPTX::Ordering(Imm);
299 switch (Ordering) {
301 return;
303 O << ".relaxed";
304 return;
306 O << ".acquire";
307 return;
309 O << ".release";
310 return;
312 O << ".acq_rel";
313 return;
316 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
317 return;
319 O << ".volatile";
320 return;
322 O << ".mmio.relaxed";
323 return;
324 }
325 } else if (Modifier == "scope") {
326 auto S = NVPTX::Scope(Imm);
327 switch (S) {
330 return;
332 O << ".sys";
333 return;
335 O << ".cta";
336 return;
338 O << ".cluster";
339 return;
341 O << ".gpu";
342 return;
343 }
345 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
346 ScopeToString(S)));
347 } else if (Modifier == "addsp") {
348 auto A = NVPTX::AddressSpace(Imm);
349 switch (A) {
351 return;
359 O << "." << addressSpaceToString(A, hasParamSubqualifiers(STI));
360 return;
361 }
363 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
364 addressSpaceToString(A)));
365 } else if (Modifier == "sign") {
366 switch (Imm) {
368 O << "s";
369 return;
371 O << "u";
372 return;
374 O << "b";
375 return;
377 O << "f";
378 return;
379 default:
380 llvm_unreachable("Unknown register type");
381 }
382 }
383 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
384}
385
387 const MCSubtargetInfo &,
388 raw_ostream &O,
389 StringRef Modifier) {
390 const MCOperand &MO = MI->getOperand(OpNum);
391 unsigned Hint = MO.getImm();
392
393 // If no hint is set, print nothing.
394 if (Hint == 0)
395 return;
396
397 // Check if L2::cache_hint mode is active.
398 bool IsCacheHintMode = NVPTX::isL2CacheHintMode(Hint);
399
400 if (Modifier == "l1") {
401 switch (NVPTX::decodeL1Eviction(Hint)) {
403 return;
405 O << ".L1::evict_unchanged";
406 return;
408 O << ".L1::evict_first";
409 return;
411 O << ".L1::evict_last";
412 return;
414 O << ".L1::no_allocate";
415 return;
416 }
417 } else if (Modifier == "l2") {
418 switch (NVPTX::decodeL2Eviction(Hint)) {
420 break;
422 O << ".L2::evict_first";
423 break;
425 O << ".L2::evict_last";
426 break;
427 }
428 if (IsCacheHintMode)
429 O << ".L2::cache_hint";
430 return;
431 } else if (Modifier == "prefetch") {
432 switch (NVPTX::decodeL2Prefetch(Hint)) {
434 return;
436 O << ".L2::64B";
437 return;
439 O << ".L2::128B";
440 return;
442 O << ".L2::256B";
443 return;
444 }
445 }
446 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
447}
448
450 const MCSubtargetInfo &,
451 raw_ostream &O) {
452 const MCOperand &MO = MI->getOperand(OpNum);
453 // If the operand is a register and valid, print ", $reg"
454 if (MO.isReg() && MO.getReg().isValid()) {
455 O << ", ";
456 printRegName(O, MO.getReg());
457 }
458}
459
461 const MCSubtargetInfo &, raw_ostream &O,
462 StringRef Modifier) {
463 const MCOperand &MO = MI->getOperand(OpNum);
464 int Imm = (int)MO.getImm();
465 if (Modifier.empty() || Modifier == "version") {
466 O << Imm; // Just print out PTX version
467 return;
468 } else if (Modifier == "aligned") {
469 // PTX63 requires '.aligned' in the name of the instruction.
470 if (Imm >= 63)
471 O << ".aligned";
472 return;
473 }
474 llvm_unreachable("Unknown Modifier");
475}
476
478 const MCSubtargetInfo &STI,
479 raw_ostream &O, StringRef Modifier) {
480 printOperand(MI, OpNum, STI, O);
481
482 if (Modifier == "add") {
483 O << ", ";
484 printOperand(MI, OpNum + 1, STI, O);
485 } else {
486 if (MI->getOperand(OpNum + 1).isImm() &&
487 MI->getOperand(OpNum + 1).getImm() == 0)
488 return; // don't print ',0' or '+0'
489 O << "+";
490 printOperand(MI, OpNum + 1, STI, O);
491 }
492}
493
495 const MCSubtargetInfo &,
496 raw_ostream &O) {
497 auto &Op = MI->getOperand(OpNum);
498 assert(Op.isImm() && "Invalid operand");
499 uint32_t Imm = (uint32_t)Op.getImm();
500 if (Imm != UINT32_MAX) {
501 O << ".pragma \"used_bytes_mask " << format_hex(Imm, 1) << "\";\n\t";
502 }
503}
504
506 const MCSubtargetInfo &STI,
507 raw_ostream &O) {
508 const MCOperand &Op = MI->getOperand(OpNum);
509 if (Op.isReg() && Op.getReg() == MCRegister::NoRegister)
510 O << "_";
511 else
512 printOperand(MI, OpNum, STI, O);
513}
514
516 const MCSubtargetInfo &, raw_ostream &O) {
517 int64_t Imm = MI->getOperand(OpNum).getImm();
518 O << formatHex(Imm) << "U";
519}
520
522 const MCSubtargetInfo &, raw_ostream &O) {
523 const MCOperand &MO = MI->getOperand(OpNum);
524 int64_t Imm = MO.getImm();
525
526 switch (Imm) {
527 default:
528 return;
530 return;
532 O << ".f4e";
533 return;
535 O << ".b4e";
536 return;
538 O << ".rc8";
539 return;
541 O << ".ecl";
542 return;
544 O << ".ecr";
545 return;
547 O << ".rc16";
548 return;
549 }
550}
551
553 const MCSubtargetInfo &,
554 raw_ostream &O) {
555 const MCOperand &MO = MI->getOperand(OpNum);
556 O << '.'
558 static_cast<nvvm::TMAReductionOp>(MO.getImm()));
559}
560
562 const MCSubtargetInfo &, raw_ostream &O) {
563 const MCOperand &MO = MI->getOperand(OpNum);
564 using CGTy = nvvm::CTAGroupKind;
565
566 switch (static_cast<CGTy>(MO.getImm())) {
567 case CGTy::CG_NONE:
568 O << "";
569 return;
570 case CGTy::CG_1:
571 O << ".cta_group::1";
572 return;
573 case CGTy::CG_2:
574 O << ".cta_group::2";
575 return;
576 }
577 llvm_unreachable("Invalid cta_group in printCTAGroup");
578}
579
581 const MCSubtargetInfo &,
582 raw_ostream &O) {
583 const MCOperand &MO = MI->getOperand(OpNum);
584 using VDTy = nvvm::TMAValidateDataPattern;
585 const VDTy Pattern = static_cast<VDTy>(MO.getImm());
586 // Qualifier omitted for disabled pattern
587 if (Pattern == VDTy::DISABLED)
588 return;
589 O << ".mbarrier::report::validity::"
591}
592
594 const MCSubtargetInfo &, raw_ostream &O,
595 StringRef Modifier) {
596 const auto Policy =
597 static_cast<nvvm::EvictPolicyType>(MI->getOperand(OpNum).getImm());
598 // Evict normal is the default priority policy for prefetch and does not print
599 // a qualifier.
601 return;
602 O << "." << nvvm::getEvictPolicyName(Policy);
603}
604
606 const MCSubtargetInfo &, raw_ostream &O,
607 StringRef Modifier) {
608 const MCOperand &MO = MI->getOperand(OpNum);
609 assert(MO.isImm() && "Invalid operand");
610 const auto Imm = MO.getImm();
611
612 if (Modifier == "RetList") {
613 assert((Imm == 1 || Imm == 0) && "Invalid return list");
614 if (Imm)
615 O << " (retval0),";
616 return;
617 }
618
619 if (Modifier == "ParamList") {
620 assert(Imm >= 0 && "Invalid parameter list");
622 [&](const auto &I) { O << "param" << I; });
623 return;
624 }
625 llvm_unreachable("Invalid modifier");
626}
627
628template <unsigned Bits>
630 const MCSubtargetInfo &, raw_ostream &O) {
631 const MCOperand &MO = MI->getOperand(OpNum);
632 assert(MO.isImm() && "Expected immediate operand");
633 assert(isInt<Bits>(MO.getImm()) &&
634 "Immediate value does not fit in specified bits");
635 uint64_t Imm = MO.getImm();
637 O << formatHex(Imm) << "U";
638}
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,...
llvm::RoundingMode roundingMode
IEEE-754R 4.3: Rounding-direction attributes.
Definition APFloat.h:359
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 printFPRoundingMode(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
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 printTMAValidateDataFlags(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
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 GetRoundingModeName(APFloat::roundingMode RM)
StringRef getEvictPolicyName(EvictPolicyType Policy)
StringRef getTMATensorReductionOpName(TMAReductionOp Op)
StringRef getTMAValidateDataPatternName(TMAValidateDataPattern Pattern)
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