1 //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // Print MCInst instructions to .ptx format.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/NVPTXInstPrinter.h"
15 #include "NVPTXUtilities.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/IR/NVVMIntrinsicUtils.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/FormatVariadic.h"
28 #define DEBUG_TYPE "asm-printer"
30 #include "NVPTXGenAsmWriter.inc"
32 NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo
&MAI
, const MCInstrInfo
&MII
,
33 const MCRegisterInfo
&MRI
)
34 : MCInstPrinter(MAI
, MII
, MRI
) {}
36 void NVPTXInstPrinter::printRegName(raw_ostream
&OS
, MCRegister Reg
) {
37 // Decode the virtual register
38 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
39 unsigned RCId
= (Reg
.id() >> 28);
41 default: report_fatal_error("Bad virtual register encoding");
43 // This is actually a physical register, so defer to the autogenerated
45 OS
<< getRegisterName(Reg
);
70 unsigned VReg
= Reg
.id() & 0x0FFFFFFF;
74 void NVPTXInstPrinter::printInst(const MCInst
*MI
, uint64_t Address
,
75 StringRef Annot
, const MCSubtargetInfo
&STI
,
77 printInstruction(MI
, Address
, OS
);
79 // Next always print the annotation.
80 printAnnotation(OS
, Annot
);
83 void NVPTXInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
85 const MCOperand
&Op
= MI
->getOperand(OpNo
);
87 unsigned Reg
= Op
.getReg();
89 } else if (Op
.isImm()) {
90 markup(O
, Markup::Immediate
) << formatImm(Op
.getImm());
92 assert(Op
.isExpr() && "Unknown operand kind in printOperand");
93 Op
.getExpr()->print(O
, &MAI
);
97 void NVPTXInstPrinter::printCvtMode(const MCInst
*MI
, int OpNum
, raw_ostream
&O
,
99 const MCOperand
&MO
= MI
->getOperand(OpNum
);
100 int64_t Imm
= MO
.getImm();
101 llvm::StringRef
Modifier(M
);
103 if (Modifier
== "ftz") {
105 if (Imm
& NVPTX::PTXCvtMode::FTZ_FLAG
)
108 } else if (Modifier
== "sat") {
110 if (Imm
& NVPTX::PTXCvtMode::SAT_FLAG
)
113 } else if (Modifier
== "relu") {
115 if (Imm
& NVPTX::PTXCvtMode::RELU_FLAG
)
118 } else if (Modifier
== "base") {
120 switch (Imm
& NVPTX::PTXCvtMode::BASE_MASK
) {
123 case NVPTX::PTXCvtMode::NONE
:
125 case NVPTX::PTXCvtMode::RNI
:
128 case NVPTX::PTXCvtMode::RZI
:
131 case NVPTX::PTXCvtMode::RMI
:
134 case NVPTX::PTXCvtMode::RPI
:
137 case NVPTX::PTXCvtMode::RN
:
140 case NVPTX::PTXCvtMode::RZ
:
143 case NVPTX::PTXCvtMode::RM
:
146 case NVPTX::PTXCvtMode::RP
:
149 case NVPTX::PTXCvtMode::RNA
:
154 llvm_unreachable("Invalid conversion modifier");
157 void NVPTXInstPrinter::printCmpMode(const MCInst
*MI
, int OpNum
, raw_ostream
&O
,
159 const MCOperand
&MO
= MI
->getOperand(OpNum
);
160 int64_t Imm
= MO
.getImm();
161 llvm::StringRef
Modifier(M
);
163 if (Modifier
== "ftz") {
165 if (Imm
& NVPTX::PTXCmpMode::FTZ_FLAG
)
168 } else if (Modifier
== "base") {
169 switch (Imm
& NVPTX::PTXCmpMode::BASE_MASK
) {
172 case NVPTX::PTXCmpMode::EQ
:
175 case NVPTX::PTXCmpMode::NE
:
178 case NVPTX::PTXCmpMode::LT
:
181 case NVPTX::PTXCmpMode::LE
:
184 case NVPTX::PTXCmpMode::GT
:
187 case NVPTX::PTXCmpMode::GE
:
190 case NVPTX::PTXCmpMode::LO
:
193 case NVPTX::PTXCmpMode::LS
:
196 case NVPTX::PTXCmpMode::HI
:
199 case NVPTX::PTXCmpMode::HS
:
202 case NVPTX::PTXCmpMode::EQU
:
205 case NVPTX::PTXCmpMode::NEU
:
208 case NVPTX::PTXCmpMode::LTU
:
211 case NVPTX::PTXCmpMode::LEU
:
214 case NVPTX::PTXCmpMode::GTU
:
217 case NVPTX::PTXCmpMode::GEU
:
220 case NVPTX::PTXCmpMode::NUM
:
223 case NVPTX::PTXCmpMode::NotANumber
:
228 llvm_unreachable("Empty Modifier");
231 void NVPTXInstPrinter::printLdStCode(const MCInst
*MI
, int OpNum
,
232 raw_ostream
&O
, const char *M
) {
233 llvm::StringRef
Modifier(M
);
234 const MCOperand
&MO
= MI
->getOperand(OpNum
);
235 int Imm
= (int)MO
.getImm();
236 if (Modifier
== "sem") {
237 auto Ordering
= NVPTX::Ordering(Imm
);
239 case NVPTX::Ordering::NotAtomic
:
241 case NVPTX::Ordering::Relaxed
:
244 case NVPTX::Ordering::Acquire
:
247 case NVPTX::Ordering::Release
:
250 case NVPTX::Ordering::Volatile
:
253 case NVPTX::Ordering::RelaxedMMIO
:
254 O
<< ".mmio.relaxed";
257 report_fatal_error(formatv(
258 "NVPTX LdStCode Printer does not support \"{}\" sem modifier. "
259 "Loads/Stores cannot be AcquireRelease or SequentiallyConsistent.",
260 OrderingToString(Ordering
)));
262 } else if (Modifier
== "scope") {
263 auto S
= NVPTX::Scope(Imm
);
265 case NVPTX::Scope::Thread
:
267 case NVPTX::Scope::System
:
270 case NVPTX::Scope::Block
:
273 case NVPTX::Scope::Cluster
:
276 case NVPTX::Scope::Device
:
281 formatv("NVPTX LdStCode Printer does not support \"{}\" sco modifier.",
283 } else if (Modifier
== "addsp") {
284 auto A
= NVPTX::AddressSpace(Imm
);
286 case NVPTX::AddressSpace::Generic
:
288 case NVPTX::AddressSpace::Global
:
289 case NVPTX::AddressSpace::Const
:
290 case NVPTX::AddressSpace::Shared
:
291 case NVPTX::AddressSpace::Param
:
292 case NVPTX::AddressSpace::Local
:
296 report_fatal_error(formatv(
297 "NVPTX LdStCode Printer does not support \"{}\" addsp modifier.",
298 AddressSpaceToString(A
)));
299 } else if (Modifier
== "sign") {
301 case NVPTX::PTXLdStInstCode::Signed
:
304 case NVPTX::PTXLdStInstCode::Unsigned
:
307 case NVPTX::PTXLdStInstCode::Untyped
:
310 case NVPTX::PTXLdStInstCode::Float
:
314 llvm_unreachable("Unknown register type");
316 } else if (Modifier
== "vec") {
318 case NVPTX::PTXLdStInstCode::V2
:
321 case NVPTX::PTXLdStInstCode::V4
:
325 // TODO: evaluate whether cases not covered by this switch are bugs
328 llvm_unreachable(formatv("Unknown Modifier: {}", Modifier
).str().c_str());
331 void NVPTXInstPrinter::printMmaCode(const MCInst
*MI
, int OpNum
, raw_ostream
&O
,
333 const MCOperand
&MO
= MI
->getOperand(OpNum
);
334 int Imm
= (int)MO
.getImm();
335 llvm::StringRef
Modifier(M
);
336 if (Modifier
.empty() || Modifier
== "version") {
337 O
<< Imm
; // Just print out PTX version
339 } else if (Modifier
== "aligned") {
340 // PTX63 requires '.aligned' in the name of the instruction.
345 llvm_unreachable("Unknown Modifier");
348 void NVPTXInstPrinter::printMemOperand(const MCInst
*MI
, int OpNum
,
349 raw_ostream
&O
, const char *M
) {
350 printOperand(MI
, OpNum
, O
);
351 llvm::StringRef
Modifier(M
);
353 if (Modifier
== "add") {
355 printOperand(MI
, OpNum
+ 1, O
);
357 if (MI
->getOperand(OpNum
+ 1).isImm() &&
358 MI
->getOperand(OpNum
+ 1).getImm() == 0)
359 return; // don't print ',0' or '+0'
361 printOperand(MI
, OpNum
+ 1, O
);
365 void NVPTXInstPrinter::printOffseti32imm(const MCInst
*MI
, int OpNum
,
366 raw_ostream
&O
, const char *Modifier
) {
367 auto &Op
= MI
->getOperand(OpNum
);
368 assert(Op
.isImm() && "Invalid operand");
369 if (Op
.getImm() != 0) {
371 printOperand(MI
, OpNum
, O
);
375 void NVPTXInstPrinter::printHexu32imm(const MCInst
*MI
, int OpNum
,
376 raw_ostream
&O
, const char *Modifier
) {
377 int64_t Imm
= MI
->getOperand(OpNum
).getImm();
378 O
<< formatHex(Imm
) << "U";
381 void NVPTXInstPrinter::printProtoIdent(const MCInst
*MI
, int OpNum
,
382 raw_ostream
&O
, const char *Modifier
) {
383 const MCOperand
&Op
= MI
->getOperand(OpNum
);
384 assert(Op
.isExpr() && "Call prototype is not an MCExpr?");
385 const MCExpr
*Expr
= Op
.getExpr();
386 const MCSymbol
&Sym
= cast
<MCSymbolRefExpr
>(Expr
)->getSymbol();
390 void NVPTXInstPrinter::printPrmtMode(const MCInst
*MI
, int OpNum
,
391 raw_ostream
&O
, const char *Modifier
) {
392 const MCOperand
&MO
= MI
->getOperand(OpNum
);
393 int64_t Imm
= MO
.getImm();
398 case NVPTX::PTXPrmtMode::NONE
:
400 case NVPTX::PTXPrmtMode::F4E
:
403 case NVPTX::PTXPrmtMode::B4E
:
406 case NVPTX::PTXPrmtMode::RC8
:
409 case NVPTX::PTXPrmtMode::ECL
:
412 case NVPTX::PTXPrmtMode::ECR
:
415 case NVPTX::PTXPrmtMode::RC16
:
421 void NVPTXInstPrinter::printTmaReductionMode(const MCInst
*MI
, int OpNum
,
423 const char *Modifier
) {
424 const MCOperand
&MO
= MI
->getOperand(OpNum
);
425 using RedTy
= llvm::nvvm::TMAReductionOp
;
427 switch (static_cast<RedTy
>(MO
.getImm())) {
454 "Invalid Reduction Op in printCpAsyncBulkTensorReductionMode");