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#include "NVPTXGenAsmWriter.inc"
33
34static bool hasParamSubqualifiers(const MCSubtargetInfo &STI) {
35 return STI.hasFeature(NVPTX::PTX83);
36}
37
41
43 // Decode a register packed by NVPTXAsmPrinter::encodeVirtualRegister.
44 const auto Kind = static_cast<NVPTX::VirtualRegisterKind>(
46
48 // This is actually a physical register, so defer to the autogenerated
49 // register printer
50 OS << getRegisterName(Reg);
51 return;
52 }
53
55 << (Reg.id() & NVPTX::VirtualRegisterNumMask);
56}
57
59 StringRef Annot, const MCSubtargetInfo &STI,
60 raw_ostream &OS) {
61 printInstruction(MI, Address, STI, OS);
62
63 // Next always print the annotation.
64 printAnnotation(OS, Annot);
65}
66
67void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
68 const MCSubtargetInfo &, raw_ostream &O) {
69 const MCOperand &Op = MI->getOperand(OpNo);
70 if (Op.isReg()) {
71 MCRegister Reg = Op.getReg();
72 printRegName(O, Reg);
73 } else if (Op.isImm()) {
74 markup(O, Markup::Immediate) << formatImm(Op.getImm());
75 } else {
76 assert(Op.isExpr() && "Unknown operand kind in printOperand");
77 MAI.printExpr(O, *Op.getExpr());
78 }
79}
80
82 const MCSubtargetInfo &, raw_ostream &O,
83 StringRef Modifier) {
84 const MCOperand &MO = MI->getOperand(OpNum);
85 int64_t Imm = MO.getImm();
86
87 if (Modifier == "ftz") {
88 // FTZ flag
90 O << ".ftz";
91 return;
92 } else if (Modifier == "sat") {
93 // SAT flag
95 O << ".sat";
96 return;
97 } else if (Modifier == "satfinite") {
98 // SATFINITE flag
100 O << ".satfinite";
101 return;
102 } else if (Modifier == "relu") {
103 // RELU flag
105 O << ".relu";
106 return;
107 } else if (Modifier == "base") {
108 // Default operand
109 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
110 default:
111 return;
113 return;
115 O << ".rni";
116 return;
118 O << ".rzi";
119 return;
121 O << ".rmi";
122 return;
124 O << ".rpi";
125 return;
127 O << ".rn";
128 return;
130 O << ".rz";
131 return;
133 O << ".rm";
134 return;
136 O << ".rp";
137 return;
139 O << ".rna";
140 return;
142 O << ".rs";
143 return;
144 }
145 }
146 llvm_unreachable("Invalid conversion modifier");
147}
148
150 const MCSubtargetInfo &, raw_ostream &O) {
151 const MCOperand &MO = MI->getOperand(OpNum);
152 const int Imm = MO.getImm();
153 if (Imm)
154 O << ".ftz";
155}
156
158 const MCSubtargetInfo &, raw_ostream &O) {
159 const MCOperand &MO = MI->getOperand(OpNum);
160 if (MO.getImm())
161 O << "multimem.";
162}
163
165 const MCSubtargetInfo &,
166 raw_ostream &O) {
167 if (MI->getOperand(OpNum).getImm())
168 O << "!";
169}
170
172 const MCSubtargetInfo &, raw_ostream &O,
173 StringRef Modifier) {
174 const MCOperand &MO = MI->getOperand(OpNum);
175 int64_t Imm = MO.getImm();
176
177 if (Modifier == "FCmp") {
178 switch (Imm) {
179 default:
180 return;
182 O << "eq";
183 return;
185 O << "ne";
186 return;
188 O << "lt";
189 return;
191 O << "le";
192 return;
194 O << "gt";
195 return;
197 O << "ge";
198 return;
200 O << "equ";
201 return;
203 O << "neu";
204 return;
206 O << "ltu";
207 return;
209 O << "leu";
210 return;
212 O << "gtu";
213 return;
215 O << "geu";
216 return;
218 O << "num";
219 return;
221 O << "nan";
222 return;
223 }
224 }
225 if (Modifier == "ICmp") {
226 switch (Imm) {
227 default:
228 llvm_unreachable("Invalid ICmp mode");
230 O << "eq";
231 return;
233 O << "ne";
234 return;
237 O << "lt";
238 return;
241 O << "le";
242 return;
245 O << "gt";
246 return;
249 O << "ge";
250 return;
251 }
252 }
253 if (Modifier == "IType") {
254 switch (Imm) {
255 default:
256 llvm_unreachable("Invalid IType");
259 O << "b";
260 return;
265 O << "s";
266 return;
271 O << "u";
272 return;
273 }
274 }
275 llvm_unreachable("Empty Modifier");
276}
277
279 const MCSubtargetInfo &STI,
280 raw_ostream &O, StringRef Modifier) {
281 const MCOperand &MO = MI->getOperand(OpNum);
282 int Imm = (int)MO.getImm();
283 if (Modifier == "sem") {
284 auto Ordering = NVPTX::Ordering(Imm);
285 switch (Ordering) {
287 return;
289 O << ".relaxed";
290 return;
292 O << ".acquire";
293 return;
295 O << ".release";
296 return;
298 O << ".acq_rel";
299 return;
302 "NVPTX AtomicCode Printer does not support \"seq_cst\" ordering.");
303 return;
305 O << ".volatile";
306 return;
308 O << ".mmio.relaxed";
309 return;
310 }
311 } else if (Modifier == "scope") {
312 auto S = NVPTX::Scope(Imm);
313 switch (S) {
316 return;
318 O << ".sys";
319 return;
321 O << ".cta";
322 return;
324 O << ".cluster";
325 return;
327 O << ".gpu";
328 return;
329 }
331 "NVPTX AtomicCode Printer does not support \"{}\" scope modifier.",
332 ScopeToString(S)));
333 } else if (Modifier == "addsp") {
334 auto A = NVPTX::AddressSpace(Imm);
335 switch (A) {
337 return;
345 O << "." << addressSpaceToString(A, hasParamSubqualifiers(STI));
346 return;
347 }
349 "NVPTX AtomicCode Printer does not support \"{}\" addsp modifier.",
350 addressSpaceToString(A)));
351 } else if (Modifier == "sign") {
352 switch (Imm) {
354 O << "s";
355 return;
357 O << "u";
358 return;
360 O << "b";
361 return;
363 O << "f";
364 return;
365 default:
366 llvm_unreachable("Unknown register type");
367 }
368 }
369 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
370}
371
373 const MCSubtargetInfo &,
374 raw_ostream &O,
375 StringRef Modifier) {
376 const MCOperand &MO = MI->getOperand(OpNum);
377 unsigned Hint = MO.getImm();
378
379 // If no hint is set, print nothing.
380 if (Hint == 0)
381 return;
382
383 // Check if L2::cache_hint mode is active.
384 bool IsCacheHintMode = NVPTX::isL2CacheHintMode(Hint);
385
386 if (Modifier == "l1") {
387 switch (NVPTX::decodeL1Eviction(Hint)) {
389 return;
391 O << ".L1::evict_unchanged";
392 return;
394 O << ".L1::evict_first";
395 return;
397 O << ".L1::evict_last";
398 return;
400 O << ".L1::no_allocate";
401 return;
402 }
403 } else if (Modifier == "l2") {
404 switch (NVPTX::decodeL2Eviction(Hint)) {
406 break;
408 O << ".L2::evict_first";
409 break;
411 O << ".L2::evict_last";
412 break;
413 }
414 if (IsCacheHintMode)
415 O << ".L2::cache_hint";
416 return;
417 } else if (Modifier == "prefetch") {
418 switch (NVPTX::decodeL2Prefetch(Hint)) {
420 return;
422 O << ".L2::64B";
423 return;
425 O << ".L2::128B";
426 return;
428 O << ".L2::256B";
429 return;
430 }
431 }
432 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier).str().c_str());
433}
434
436 const MCSubtargetInfo &,
437 raw_ostream &O) {
438 const MCOperand &MO = MI->getOperand(OpNum);
439 // If the operand is a register and valid, print ", $reg"
440 if (MO.isReg() && MO.getReg().isValid()) {
441 O << ", ";
442 printRegName(O, MO.getReg());
443 }
444}
445
447 const MCSubtargetInfo &, raw_ostream &O,
448 StringRef Modifier) {
449 const MCOperand &MO = MI->getOperand(OpNum);
450 int Imm = (int)MO.getImm();
451 if (Modifier.empty() || Modifier == "version") {
452 O << Imm; // Just print out PTX version
453 return;
454 } else if (Modifier == "aligned") {
455 // PTX63 requires '.aligned' in the name of the instruction.
456 if (Imm >= 63)
457 O << ".aligned";
458 return;
459 }
460 llvm_unreachable("Unknown Modifier");
461}
462
464 const MCSubtargetInfo &STI,
465 raw_ostream &O, StringRef Modifier) {
466 printOperand(MI, OpNum, STI, O);
467
468 if (Modifier == "add") {
469 O << ", ";
470 printOperand(MI, OpNum + 1, STI, O);
471 } else {
472 if (MI->getOperand(OpNum + 1).isImm() &&
473 MI->getOperand(OpNum + 1).getImm() == 0)
474 return; // don't print ',0' or '+0'
475 O << "+";
476 printOperand(MI, OpNum + 1, STI, O);
477 }
478}
479
481 const MCSubtargetInfo &,
482 raw_ostream &O) {
483 auto &Op = MI->getOperand(OpNum);
484 assert(Op.isImm() && "Invalid operand");
485 uint32_t Imm = (uint32_t)Op.getImm();
486 if (Imm != UINT32_MAX) {
487 O << ".pragma \"used_bytes_mask " << format_hex(Imm, 1) << "\";\n\t";
488 }
489}
490
492 const MCSubtargetInfo &STI,
493 raw_ostream &O) {
494 const MCOperand &Op = MI->getOperand(OpNum);
495 if (Op.isReg() && Op.getReg() == MCRegister::NoRegister)
496 O << "_";
497 else
498 printOperand(MI, OpNum, STI, O);
499}
500
502 const MCSubtargetInfo &, raw_ostream &O) {
503 int64_t Imm = MI->getOperand(OpNum).getImm();
504 O << formatHex(Imm) << "U";
505}
506
508 const MCSubtargetInfo &, raw_ostream &O) {
509 const MCOperand &MO = MI->getOperand(OpNum);
510 int64_t Imm = MO.getImm();
511
512 switch (Imm) {
513 default:
514 return;
516 return;
518 O << ".f4e";
519 return;
521 O << ".b4e";
522 return;
524 O << ".rc8";
525 return;
527 O << ".ecl";
528 return;
530 O << ".ecr";
531 return;
533 O << ".rc16";
534 return;
535 }
536}
537
539 const MCSubtargetInfo &,
540 raw_ostream &O) {
541 const MCOperand &MO = MI->getOperand(OpNum);
542 O << '.'
544 static_cast<nvvm::TMAReductionOp>(MO.getImm()));
545}
546
548 const MCSubtargetInfo &, raw_ostream &O) {
549 const MCOperand &MO = MI->getOperand(OpNum);
550 using CGTy = nvvm::CTAGroupKind;
551
552 switch (static_cast<CGTy>(MO.getImm())) {
553 case CGTy::CG_NONE:
554 O << "";
555 return;
556 case CGTy::CG_1:
557 O << ".cta_group::1";
558 return;
559 case CGTy::CG_2:
560 O << ".cta_group::2";
561 return;
562 }
563 llvm_unreachable("Invalid cta_group in printCTAGroup");
564}
565
567 const MCSubtargetInfo &, raw_ostream &O,
568 StringRef Modifier) {
569 const MCOperand &MO = MI->getOperand(OpNum);
570 assert(MO.isImm() && "Invalid operand");
571 const auto Imm = MO.getImm();
572
573 if (Modifier == "RetList") {
574 assert((Imm == 1 || Imm == 0) && "Invalid return list");
575 if (Imm)
576 O << " (retval0),";
577 return;
578 }
579
580 if (Modifier == "ParamList") {
581 assert(Imm >= 0 && "Invalid parameter list");
583 [&](const auto &I) { O << "param" << I; });
584 return;
585 }
586 llvm_unreachable("Invalid modifier");
587}
588
589template <unsigned Bits>
591 const MCSubtargetInfo &, raw_ostream &O) {
592 const MCOperand &MO = MI->getOperand(OpNum);
593 assert(MO.isImm() && "Expected immediate operand");
594 assert(isInt<Bits>(MO.getImm()) &&
595 "Immediate value does not fit in specified bits");
596 uint64_t Imm = MO.getImm();
597 Imm &= maskTrailingOnes<uint64_t>(Bits);
598 O << formatHex(Imm) << "U";
599}
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
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 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
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:317
@ SharedCluster
Definition NVPTX.h:310
@ EntryParam
Definition NVPTX.h:311
L2Prefetch decodeL2Prefetch(unsigned Hint)
Definition NVPTX.h:379
L1Eviction decodeL1Eviction(unsigned Hint)
Definition NVPTX.h:371
L2Eviction decodeL2Eviction(unsigned Hint)
Definition NVPTX.h:375
bool isL2CacheHintMode(unsigned Hint)
Definition NVPTX.h:383
@ DefaultDevice
Definition NVPTX.h:299
constexpr unsigned VirtualRegisterNumMask
@ RelaxedMMIO
Definition NVPTX.h:289
@ AcquireRelease
Definition NVPTX.h:285
@ NotAtomic
Definition NVPTX.h:278
@ SequentiallyConsistent
Definition NVPTX.h:286
constexpr unsigned VirtualRegisterKindShift
StringRef getVirtualRegisterPrefix(VirtualRegisterKind Kind)
The name prefix shared by all virtual registers of Kind.
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)
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