LLVM 22.0.0git
AMDGPUInstPrinter.cpp
Go to the documentation of this file.
1//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
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// \file
8//===----------------------------------------------------------------------===//
9
10#include "AMDGPUInstPrinter.h"
12#include "SIDefines.h"
15#include "llvm/MC/MCAsmInfo.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrDesc.h"
19#include "llvm/MC/MCInstrInfo.h"
23
24using namespace llvm;
25using namespace llvm::AMDGPU;
26
28 // FIXME: The current implementation of
29 // AsmParser::parseRegisterOrRegisterNumber in MC implies we either emit this
30 // as an integer or we provide a name which represents a physical register.
31 // For CFI instructions we really want to emit a name for the DWARF register
32 // instead, because there may be multiple DWARF registers corresponding to a
33 // single physical register. One case where this problem manifests is with
34 // wave32/wave64 where using the physical register name is ambiguous: if we
35 // write e.g. `.cfi_undefined v0` we lose information about the wavefront
36 // size which we need to encode the register in the final DWARF. Ideally we
37 // would extend MC to support parsing DWARF register names so we could do
38 // something like `.cfi_undefined dwarf_wave32_v0`. For now we just live with
39 // non-pretty DWARF register names in assembly text.
40 OS << Reg.id();
41}
42
44 StringRef Annot, const MCSubtargetInfo &STI,
45 raw_ostream &OS) {
46 printInstruction(MI, Address, STI, OS);
47 printAnnotation(OS, Annot);
48}
49
50void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
51 const MCSubtargetInfo &STI,
52 raw_ostream &O) {
53 const MCOperand &Op = MI->getOperand(OpNo);
54 if (Op.isExpr()) {
55 MAI.printExpr(O, *Op.getExpr());
56 return;
57 }
58
59 // It's possible to end up with a 32-bit literal used with a 16-bit operand
60 // with ignored high bits. Print as 32-bit anyway in that case.
61 int64_t Imm = Op.getImm();
62 if (isInt<16>(Imm) || isUInt<16>(Imm))
63 O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
64 else
65 printU32ImmOperand(MI, OpNo, STI, O);
66}
67
68void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
69 raw_ostream &O) {
70 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
71}
72
73void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
74 const MCSubtargetInfo &STI,
75 raw_ostream &O) {
76 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
77}
78
79void AMDGPUInstPrinter::printFP64ImmOperand(const MCInst *MI, unsigned OpNo,
80 const MCSubtargetInfo &STI,
81 raw_ostream &O) {
82 // KIMM64
83 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
84 uint64_t Imm = MI->getOperand(OpNo).getImm();
85 printLiteral64(Desc, Imm, STI, O, /*IsFP=*/true);
86}
87
88void AMDGPUInstPrinter::printNamedBit(const MCInst *MI, unsigned OpNo,
89 raw_ostream &O, StringRef BitName) {
90 if (MI->getOperand(OpNo).getImm()) {
91 O << ' ' << BitName;
92 }
93}
94
95void AMDGPUInstPrinter::printOffset(const MCInst *MI, unsigned OpNo,
96 const MCSubtargetInfo &STI,
97 raw_ostream &O) {
98 uint32_t Imm = MI->getOperand(OpNo).getImm();
99 if (Imm != 0) {
100 O << " offset:";
101
102 // GFX12 uses a 24-bit signed offset for VBUFFER.
103 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
104 bool IsVBuffer = Desc.TSFlags & (SIInstrFlags::MUBUF | SIInstrFlags::MTBUF);
105 if (AMDGPU::isGFX12(STI) && IsVBuffer)
106 O << formatDec(SignExtend32<24>(Imm));
107 else
108 printU16ImmDecOperand(MI, OpNo, O);
109 }
110}
111
112void AMDGPUInstPrinter::printFlatOffset(const MCInst *MI, unsigned OpNo,
113 const MCSubtargetInfo &STI,
114 raw_ostream &O) {
115 uint32_t Imm = MI->getOperand(OpNo).getImm();
116 if (Imm != 0) {
117 O << " offset:";
118
119 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
120 bool AllowNegative = (Desc.TSFlags & (SIInstrFlags::FlatGlobal |
122 AMDGPU::isGFX12(STI);
123
124 if (AllowNegative) // Signed offset
126 else // Unsigned offset
127 printU16ImmDecOperand(MI, OpNo, O);
128 }
129}
130
131void AMDGPUInstPrinter::printSMRDOffset8(const MCInst *MI, unsigned OpNo,
132 const MCSubtargetInfo &STI,
133 raw_ostream &O) {
134 printU32ImmOperand(MI, OpNo, STI, O);
135}
136
137void AMDGPUInstPrinter::printSMEMOffset(const MCInst *MI, unsigned OpNo,
138 const MCSubtargetInfo &STI,
139 raw_ostream &O) {
140 O << formatHex(MI->getOperand(OpNo).getImm());
141}
142
143void AMDGPUInstPrinter::printSMRDLiteralOffset(const MCInst *MI, unsigned OpNo,
144 const MCSubtargetInfo &STI,
145 raw_ostream &O) {
146 printU32ImmOperand(MI, OpNo, STI, O);
147}
148
149void AMDGPUInstPrinter::printCPol(const MCInst *MI, unsigned OpNo,
150 const MCSubtargetInfo &STI, raw_ostream &O) {
151 auto Imm = MI->getOperand(OpNo).getImm();
152
153 if (AMDGPU::isGFX12Plus(STI)) {
154 const int64_t TH = Imm & CPol::TH;
155 const int64_t Scope = Imm & CPol::SCOPE;
156
157 if (Imm & CPol::SCAL)
158 O << " scale_offset";
159
160 printTH(MI, TH, Scope, O);
161 printScope(Scope, O);
162
163 if (Imm & CPol::NV)
164 O << " nv";
165
166 return;
167 }
168
169 if (Imm & CPol::GLC)
170 O << ((AMDGPU::isGFX940(STI) &&
171 !(MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::SMRD)) ? " sc0"
172 : " glc");
173 if (Imm & CPol::SLC)
174 O << (AMDGPU::isGFX940(STI) ? " nt" : " slc");
175 if ((Imm & CPol::DLC) && AMDGPU::isGFX10Plus(STI))
176 O << " dlc";
177 if ((Imm & CPol::SCC) && AMDGPU::isGFX90A(STI))
178 O << (AMDGPU::isGFX940(STI) ? " sc1" : " scc");
179 if (Imm & ~CPol::ALL_pregfx12)
180 O << " /* unexpected cache policy bit */";
181}
182
183void AMDGPUInstPrinter::printTH(const MCInst *MI, int64_t TH, int64_t Scope,
184 raw_ostream &O) {
185 // For th = 0 do not print this field
186 if (TH == 0)
187 return;
188
189 const unsigned Opcode = MI->getOpcode();
190 const MCInstrDesc &TID = MII.get(Opcode);
191 unsigned THType = AMDGPU::getTemporalHintType(TID);
192 bool IsStore = (THType == AMDGPU::CPol::TH_TYPE_STORE);
193
194 O << " th:";
195
196 if (THType == AMDGPU::CPol::TH_TYPE_ATOMIC) {
197 O << "TH_ATOMIC_";
199 if (Scope >= AMDGPU::CPol::SCOPE_DEV)
200 O << "CASCADE" << (TH & AMDGPU::CPol::TH_ATOMIC_NT ? "_NT" : "_RT");
201 else
202 O << formatHex(TH);
203 } else if (TH & AMDGPU::CPol::TH_ATOMIC_NT)
204 O << "NT" << (TH & AMDGPU::CPol::TH_ATOMIC_RETURN ? "_RETURN" : "");
205 else if (TH & AMDGPU::CPol::TH_ATOMIC_RETURN)
206 O << "RETURN";
207 else
208 O << formatHex(TH);
209 } else {
210 if (!IsStore && TH == AMDGPU::CPol::TH_RESERVED)
211 O << formatHex(TH);
212 else {
213 O << (IsStore ? "TH_STORE_" : "TH_LOAD_");
214 switch (TH) {
216 O << "NT";
217 break;
219 O << "HT";
220 break;
221 case AMDGPU::CPol::TH_BYPASS: // or LU or WB
222 O << (Scope == AMDGPU::CPol::SCOPE_SYS ? "BYPASS"
223 : (IsStore ? "WB" : "LU"));
224 break;
226 O << "NT_RT";
227 break;
229 O << "RT_NT";
230 break;
232 O << "NT_HT";
233 break;
235 O << "NT_WB";
236 break;
237 default:
238 llvm_unreachable("unexpected th value");
239 }
240 }
241 }
242}
243
244void AMDGPUInstPrinter::printScope(int64_t Scope, raw_ostream &O) {
245 if (Scope == CPol::SCOPE_CU)
246 return;
247
248 O << " scope:";
249
250 if (Scope == CPol::SCOPE_SE)
251 O << "SCOPE_SE";
252 else if (Scope == CPol::SCOPE_DEV)
253 O << "SCOPE_DEV";
254 else if (Scope == CPol::SCOPE_SYS)
255 O << "SCOPE_SYS";
256 else
257 llvm_unreachable("unexpected scope policy value");
258}
259
260void AMDGPUInstPrinter::printDim(const MCInst *MI, unsigned OpNo,
261 const MCSubtargetInfo &STI, raw_ostream &O) {
262 unsigned Dim = MI->getOperand(OpNo).getImm();
263 O << " dim:SQ_RSRC_IMG_";
264
265 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
266 if (DimInfo)
267 O << DimInfo->AsmSuffix;
268 else
269 O << Dim;
270}
271
272void AMDGPUInstPrinter::printR128A16(const MCInst *MI, unsigned OpNo,
273 const MCSubtargetInfo &STI, raw_ostream &O) {
274 if (STI.hasFeature(AMDGPU::FeatureR128A16))
275 printNamedBit(MI, OpNo, O, "a16");
276 else
277 printNamedBit(MI, OpNo, O, "r128");
278}
279
280void AMDGPUInstPrinter::printFORMAT(const MCInst *MI, unsigned OpNo,
281 const MCSubtargetInfo &STI,
282 raw_ostream &O) {
283}
284
285void AMDGPUInstPrinter::printSymbolicFormat(const MCInst *MI,
286 const MCSubtargetInfo &STI,
287 raw_ostream &O) {
288 using namespace llvm::AMDGPU::MTBUFFormat;
289
290 int OpNo =
291 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::format);
292 assert(OpNo != -1);
293
294 unsigned Val = MI->getOperand(OpNo).getImm();
295 if (AMDGPU::isGFX10Plus(STI)) {
296 if (Val == UFMT_DEFAULT)
297 return;
298 if (isValidUnifiedFormat(Val, STI)) {
299 O << " format:[" << getUnifiedFormatName(Val, STI) << ']';
300 } else {
301 O << " format:" << Val;
302 }
303 } else {
304 if (Val == DFMT_NFMT_DEFAULT)
305 return;
306 if (isValidDfmtNfmt(Val, STI)) {
307 unsigned Dfmt;
308 unsigned Nfmt;
309 decodeDfmtNfmt(Val, Dfmt, Nfmt);
310 O << " format:[";
311 if (Dfmt != DFMT_DEFAULT) {
312 O << getDfmtName(Dfmt);
313 if (Nfmt != NFMT_DEFAULT) {
314 O << ',';
315 }
316 }
317 if (Nfmt != NFMT_DEFAULT) {
318 O << getNfmtName(Nfmt, STI);
319 }
320 O << ']';
321 } else {
322 O << " format:" << Val;
323 }
324 }
325}
326
327// \returns a low 256 vgpr representing a high vgpr \p Reg [v256..v1023] or
328// \p Reg itself otherwise.
330 unsigned Enc = MRI.getEncodingValue(Reg);
331 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
332 if (Idx < 0x100)
333 return Reg;
334
336 return RC->getRegister(Idx % 0x100);
337}
338
339// Restore MSBs of a VGPR above 255 from the MCInstrAnalysis.
340static MCPhysReg getRegFromMIA(MCPhysReg Reg, unsigned OpNo,
341 const MCInstrDesc &Desc,
342 const MCRegisterInfo &MRI,
343 const AMDGPUMCInstrAnalysis &MIA) {
344 unsigned VgprMSBs = MIA.getVgprMSBs();
345 if (!VgprMSBs)
346 return Reg;
347
348 unsigned Enc = MRI.getEncodingValue(Reg);
349 if (!(Enc & AMDGPU::HWEncoding::IS_VGPR))
350 return Reg;
351
353 if (!Ops.first)
354 return Reg;
355 unsigned Opc = Desc.getOpcode();
356 unsigned I;
357 for (I = 0; I < 4; ++I) {
358 if (Ops.first[I] != AMDGPU::OpName::NUM_OPERAND_NAMES &&
359 (unsigned)AMDGPU::getNamedOperandIdx(Opc, Ops.first[I]) == OpNo)
360 break;
361 if (Ops.second && Ops.second[I] != AMDGPU::OpName::NUM_OPERAND_NAMES &&
362 (unsigned)AMDGPU::getNamedOperandIdx(Opc, Ops.second[I]) == OpNo)
363 break;
364 }
365 if (I == 4)
366 return Reg;
367 unsigned OpMSBs = (VgprMSBs >> (I * 2)) & 3;
368 if (!OpMSBs)
369 return Reg;
370 if (MCRegister NewReg = AMDGPU::getVGPRWithMSBs(Reg, OpMSBs, MRI))
371 return NewReg;
372 return Reg;
373}
374
376 const MCRegisterInfo &MRI) {
377#if !defined(NDEBUG)
378 switch (Reg.id()) {
379 case AMDGPU::FP_REG:
380 case AMDGPU::SP_REG:
381 case AMDGPU::PRIVATE_RSRC_REG:
382 llvm_unreachable("pseudo-register should not ever be emitted");
383 default:
384 break;
385 }
386#endif
387
388 unsigned PrintReg = getRegForPrinting(Reg, MRI);
389 O << getRegisterName(PrintReg);
390
391 if (PrintReg != Reg.id())
392 O << " /*" << getRegisterName(Reg) << "*/";
393}
394
396 unsigned OpNo, raw_ostream &O,
397 const MCRegisterInfo &MRI) {
398 if (MIA)
399 Reg = getRegFromMIA(Reg, OpNo, MII.get(Opc), MRI,
400 *static_cast<const AMDGPUMCInstrAnalysis *>(MIA));
401 printRegOperand(Reg, O, MRI);
402}
403
404void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
405 const MCSubtargetInfo &STI, raw_ostream &O) {
406 auto Opcode = MI->getOpcode();
407 auto Flags = MII.get(Opcode).TSFlags;
408 if (OpNo == 0) {
409 if (Flags & SIInstrFlags::VOP3 && Flags & SIInstrFlags::DPP)
410 O << "_e64_dpp";
411 else if (Flags & SIInstrFlags::VOP3) {
412 if (!getVOP3IsSingle(Opcode))
413 O << "_e64";
414 } else if (Flags & SIInstrFlags::DPP)
415 O << "_dpp";
416 else if (Flags & SIInstrFlags::SDWA)
417 O << "_sdwa";
418 else if (((Flags & SIInstrFlags::VOP1) && !getVOP1IsSingle(Opcode)) ||
419 ((Flags & SIInstrFlags::VOP2) && !getVOP2IsSingle(Opcode)))
420 O << "_e32";
421 O << " ";
422 }
423
424 printRegularOperand(MI, OpNo, STI, O);
425
426 // Print default vcc/vcc_lo operand.
427 switch (Opcode) {
428 default: break;
429
430 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx10:
431 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx10:
432 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
433 case AMDGPU::V_ADD_CO_CI_U32_sdwa_gfx10:
434 case AMDGPU::V_SUB_CO_CI_U32_sdwa_gfx10:
435 case AMDGPU::V_SUBREV_CO_CI_U32_sdwa_gfx10:
436 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx10:
437 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx10:
438 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx10:
439 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx10:
440 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx10:
441 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx10:
442 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx11:
443 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx11:
444 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx11:
445 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx11:
446 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx11:
447 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx11:
448 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx11:
449 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx11:
450 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx11:
451 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx12:
452 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx12:
453 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx12:
454 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx12:
455 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx12:
456 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx12:
457 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx12:
458 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx12:
459 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx12:
460 printDefaultVccOperand(false, STI, O);
461 break;
462 }
463}
464
465void AMDGPUInstPrinter::printVINTRPDst(const MCInst *MI, unsigned OpNo,
466 const MCSubtargetInfo &STI, raw_ostream &O) {
467 if (AMDGPU::isSI(STI) || AMDGPU::isCI(STI))
468 O << " ";
469 else
470 O << "_e32 ";
471
472 printRegularOperand(MI, OpNo, STI, O);
473}
474
475void AMDGPUInstPrinter::printImmediateInt16(uint32_t Imm,
476 const MCSubtargetInfo &STI,
477 raw_ostream &O) {
478 int32_t SImm = static_cast<int32_t>(Imm);
479 if (isInlinableIntLiteral(SImm)) {
480 O << SImm;
481 return;
482 }
483
484 if (printImmediateFloat32(Imm, STI, O))
485 return;
486
487 O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
488}
489
491 raw_ostream &O) {
492 if (Imm == 0x3C00)
493 O << "1.0";
494 else if (Imm == 0xBC00)
495 O << "-1.0";
496 else if (Imm == 0x3800)
497 O << "0.5";
498 else if (Imm == 0xB800)
499 O << "-0.5";
500 else if (Imm == 0x4000)
501 O << "2.0";
502 else if (Imm == 0xC000)
503 O << "-2.0";
504 else if (Imm == 0x4400)
505 O << "4.0";
506 else if (Imm == 0xC400)
507 O << "-4.0";
508 else if (Imm == 0x3118 && STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
509 O << "0.15915494";
510 else
511 return false;
512
513 return true;
514}
515
517 raw_ostream &O) {
518 if (Imm == 0x3F80)
519 O << "1.0";
520 else if (Imm == 0xBF80)
521 O << "-1.0";
522 else if (Imm == 0x3F00)
523 O << "0.5";
524 else if (Imm == 0xBF00)
525 O << "-0.5";
526 else if (Imm == 0x4000)
527 O << "2.0";
528 else if (Imm == 0xC000)
529 O << "-2.0";
530 else if (Imm == 0x4080)
531 O << "4.0";
532 else if (Imm == 0xC080)
533 O << "-4.0";
534 else if (Imm == 0x3E22 && STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
535 O << "0.15915494";
536 else
537 return false;
538
539 return true;
540}
541
542void AMDGPUInstPrinter::printImmediateBF16(uint32_t Imm,
543 const MCSubtargetInfo &STI,
544 raw_ostream &O) {
545 int16_t SImm = static_cast<int16_t>(Imm);
546 if (isInlinableIntLiteral(SImm)) {
547 O << SImm;
548 return;
549 }
550
551 if (printImmediateBFloat16(static_cast<uint16_t>(Imm), STI, O))
552 return;
553
554 O << formatHex(static_cast<uint64_t>(Imm));
555}
556
557void AMDGPUInstPrinter::printImmediateF16(uint32_t Imm,
558 const MCSubtargetInfo &STI,
559 raw_ostream &O) {
560 int16_t SImm = static_cast<int16_t>(Imm);
561 if (isInlinableIntLiteral(SImm)) {
562 O << SImm;
563 return;
564 }
565
566 uint16_t HImm = static_cast<uint16_t>(Imm);
567 if (printImmediateFP16(HImm, STI, O))
568 return;
569
570 uint64_t Imm16 = static_cast<uint16_t>(Imm);
571 O << formatHex(Imm16);
572}
573
574void AMDGPUInstPrinter::printImmediateV216(uint32_t Imm, uint8_t OpType,
575 const MCSubtargetInfo &STI,
576 raw_ostream &O) {
577 int32_t SImm = static_cast<int32_t>(Imm);
578 if (isInlinableIntLiteral(SImm)) {
579 O << SImm;
580 return;
581 }
582
583 switch (OpType) {
586 if (printImmediateFloat32(Imm, STI, O))
587 return;
588 break;
591 if (isUInt<16>(Imm) &&
592 printImmediateFP16(static_cast<uint16_t>(Imm), STI, O))
593 return;
594 break;
597 if (isUInt<16>(Imm) &&
598 printImmediateBFloat16(static_cast<uint16_t>(Imm), STI, O))
599 return;
600 break;
602 break;
603 default:
604 llvm_unreachable("bad operand type");
605 }
606
607 O << formatHex(static_cast<uint64_t>(Imm));
608}
609
610bool AMDGPUInstPrinter::printImmediateFloat32(uint32_t Imm,
611 const MCSubtargetInfo &STI,
612 raw_ostream &O) {
613 if (Imm == llvm::bit_cast<uint32_t>(0.0f))
614 O << "0.0";
615 else if (Imm == llvm::bit_cast<uint32_t>(1.0f))
616 O << "1.0";
617 else if (Imm == llvm::bit_cast<uint32_t>(-1.0f))
618 O << "-1.0";
619 else if (Imm == llvm::bit_cast<uint32_t>(0.5f))
620 O << "0.5";
621 else if (Imm == llvm::bit_cast<uint32_t>(-0.5f))
622 O << "-0.5";
623 else if (Imm == llvm::bit_cast<uint32_t>(2.0f))
624 O << "2.0";
625 else if (Imm == llvm::bit_cast<uint32_t>(-2.0f))
626 O << "-2.0";
627 else if (Imm == llvm::bit_cast<uint32_t>(4.0f))
628 O << "4.0";
629 else if (Imm == llvm::bit_cast<uint32_t>(-4.0f))
630 O << "-4.0";
631 else if (Imm == 0x3e22f983 &&
632 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
633 O << "0.15915494";
634 else
635 return false;
636
637 return true;
638}
639
640void AMDGPUInstPrinter::printImmediate32(uint32_t Imm,
641 const MCSubtargetInfo &STI,
642 raw_ostream &O) {
643 int32_t SImm = static_cast<int32_t>(Imm);
644 if (isInlinableIntLiteral(SImm)) {
645 O << SImm;
646 return;
647 }
648
649 if (printImmediateFloat32(Imm, STI, O))
650 return;
651
652 O << formatHex(static_cast<uint64_t>(Imm));
653}
654
655void AMDGPUInstPrinter::printImmediate64(const MCInstrDesc &Desc, uint64_t Imm,
656 const MCSubtargetInfo &STI,
657 raw_ostream &O, bool IsFP) {
658 int64_t SImm = static_cast<int64_t>(Imm);
659 if (SImm >= -16 && SImm <= 64) {
660 O << SImm;
661 return;
662 }
663
664 if (Imm == llvm::bit_cast<uint64_t>(0.0))
665 O << "0.0";
666 else if (Imm == llvm::bit_cast<uint64_t>(1.0))
667 O << "1.0";
668 else if (Imm == llvm::bit_cast<uint64_t>(-1.0))
669 O << "-1.0";
670 else if (Imm == llvm::bit_cast<uint64_t>(0.5))
671 O << "0.5";
672 else if (Imm == llvm::bit_cast<uint64_t>(-0.5))
673 O << "-0.5";
674 else if (Imm == llvm::bit_cast<uint64_t>(2.0))
675 O << "2.0";
676 else if (Imm == llvm::bit_cast<uint64_t>(-2.0))
677 O << "-2.0";
678 else if (Imm == llvm::bit_cast<uint64_t>(4.0))
679 O << "4.0";
680 else if (Imm == llvm::bit_cast<uint64_t>(-4.0))
681 O << "-4.0";
682 else if (Imm == 0x3fc45f306dc9c882 &&
683 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
684 O << "0.15915494309189532";
685 else
686 printLiteral64(Desc, Imm, STI, O, IsFP);
687}
688
689void AMDGPUInstPrinter::printLiteral64(const MCInstrDesc &Desc, uint64_t Imm,
690 const MCSubtargetInfo &STI,
691 raw_ostream &O, bool IsFP) {
692 // This part needs to align with AMDGPUOperand::addLiteralImmOperand.
693 bool CanUse64BitLiterals =
694 STI.hasFeature(AMDGPU::Feature64BitLiterals) &&
696 if (IsFP) {
697 if (CanUse64BitLiterals && Lo_32(Imm))
698 O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
699 else
700 O << formatHex(static_cast<uint64_t>(Hi_32(Imm)));
701 } else {
702 if (CanUse64BitLiterals && (!isInt<32>(Imm) || !isUInt<32>(Imm)))
703 O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
704 else
705 O << formatHex(static_cast<uint64_t>(Imm));
706 }
707}
708
709void AMDGPUInstPrinter::printBLGP(const MCInst *MI, unsigned OpNo,
710 const MCSubtargetInfo &STI,
711 raw_ostream &O) {
712 unsigned Imm = MI->getOperand(OpNo).getImm();
713 if (!Imm)
714 return;
715
716 if (AMDGPU::isGFX940(STI)) {
717 switch (MI->getOpcode()) {
718 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_acd:
719 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_vcd:
720 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_acd:
721 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_vcd:
722 O << " neg:[" << (Imm & 1) << ',' << ((Imm >> 1) & 1) << ','
723 << ((Imm >> 2) & 1) << ']';
724 return;
725 }
726 }
727
728 O << " blgp:" << Imm;
729}
730
731void AMDGPUInstPrinter::printDefaultVccOperand(bool FirstOperand,
732 const MCSubtargetInfo &STI,
733 raw_ostream &O) {
734 if (!FirstOperand)
735 O << ", ";
736 printRegOperand(STI.hasFeature(AMDGPU::FeatureWavefrontSize32)
737 ? AMDGPU::VCC_LO
738 : AMDGPU::VCC,
739 O, MRI);
740 if (FirstOperand)
741 O << ", ";
742}
743
744bool AMDGPUInstPrinter::needsImpliedVcc(const MCInstrDesc &Desc,
745 unsigned OpNo) const {
746 return OpNo == 0 && (Desc.TSFlags & SIInstrFlags::DPP) &&
747 (Desc.TSFlags & SIInstrFlags::VOPC) &&
748 !isVOPCAsmOnly(Desc.getOpcode()) &&
749 (Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC) ||
750 Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC_LO));
751}
752
753// Print default vcc/vcc_lo operand of VOPC.
754void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
755 const MCSubtargetInfo &STI,
756 raw_ostream &O) {
757 unsigned Opc = MI->getOpcode();
758 const MCInstrDesc &Desc = MII.get(Opc);
759 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
760 // 0, 1 and 2 are the first printed operands in different cases
761 // If there are printed modifiers, printOperandAndFPInputMods or
762 // printOperandAndIntInputMods will be called instead
763 if ((OpNo == 0 ||
764 (OpNo == 1 && (Desc.TSFlags & SIInstrFlags::DPP) && ModIdx != -1)) &&
765 (Desc.TSFlags & SIInstrFlags::VOPC) && !isVOPCAsmOnly(Desc.getOpcode()) &&
766 (Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC) ||
767 Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC_LO)))
768 printDefaultVccOperand(true, STI, O);
769
770 printRegularOperand(MI, OpNo, STI, O);
771}
772
773// Print operands after vcc or modifier handling.
774void AMDGPUInstPrinter::printRegularOperand(const MCInst *MI, unsigned OpNo,
775 const MCSubtargetInfo &STI,
776 raw_ostream &O) {
777 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
778
779 if (OpNo >= MI->getNumOperands()) {
780 O << "/*Missing OP" << OpNo << "*/";
781 return;
782 }
783
784 const MCOperand &Op = MI->getOperand(OpNo);
785 if (Op.isReg()) {
786 printRegOperand(Op.getReg(), MI->getOpcode(), OpNo, O, MRI);
787
788 // Check if operand register class contains register used.
789 // Intention: print disassembler message when invalid code is decoded,
790 // for example sgpr register used in VReg or VISrc(VReg or imm) operand.
791 int RCID = Desc.operands()[OpNo].RegClass;
792 if (RCID != -1) {
793 const MCRegisterClass RC = MRI.getRegClass(RCID);
794 auto Reg = mc2PseudoReg(Op.getReg());
795 if (!RC.contains(Reg) && !isInlineValue(Reg)) {
796 O << "/*Invalid register, operand has \'" << MRI.getRegClassName(&RC)
797 << "\' register class*/";
798 }
799 }
800 } else if (Op.isImm()) {
801 const uint8_t OpTy = Desc.operands()[OpNo].OperandType;
802 switch (OpTy) {
813 printImmediate32(Op.getImm(), STI, O);
814 break;
817 printImmediate64(Desc, Op.getImm(), STI, O, false);
818 break;
822 printImmediate64(Desc, Op.getImm(), STI, O, true);
823 break;
826 printImmediateInt16(Op.getImm(), STI, O);
827 break;
830 printImmediateF16(Op.getImm(), STI, O);
831 break;
834 printImmediateBF16(Op.getImm(), STI, O);
835 break;
843 printImmediateV216(Op.getImm(), OpTy, STI, O);
844 break;
847 O << formatDec(Op.getImm());
848 break;
850 // Disassembler does not fail when operand should not allow immediate
851 // operands but decodes them into 32bit immediate operand.
852 printImmediate32(Op.getImm(), STI, O);
853 O << "/*Invalid immediate*/";
854 break;
855 default:
856 // We hit this for the immediate instruction bits that don't yet have a
857 // custom printer.
858 llvm_unreachable("unexpected immediate operand type");
859 }
860 } else if (Op.isExpr()) {
861 const MCExpr *Exp = Op.getExpr();
862 MAI.printExpr(O, *Exp);
863 } else {
864 O << "/*INV_OP*/";
865 }
866
867 // Print default vcc/vcc_lo operand of v_cndmask_b32_e32.
868 switch (MI->getOpcode()) {
869 default: break;
870
871 case AMDGPU::V_CNDMASK_B32_e32_gfx10:
872 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx10:
873 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx10:
874 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
875 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx10:
876 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx10:
877 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx10:
878 case AMDGPU::V_CNDMASK_B32_dpp8_gfx10:
879 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx10:
880 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx10:
881 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx10:
882 case AMDGPU::V_CNDMASK_B32_e32_gfx11:
883 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx11:
884 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx11:
885 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx11:
886 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx11:
887 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx11:
888 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx11:
889 case AMDGPU::V_CNDMASK_B32_dpp8_gfx11:
890 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx11:
891 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx11:
892 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx11:
893 case AMDGPU::V_CNDMASK_B32_e32_gfx12:
894 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx12:
895 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx12:
896 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx12:
897 case AMDGPU::V_CNDMASK_B32_dpp_gfx12:
898 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx12:
899 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx12:
900 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx12:
901 case AMDGPU::V_CNDMASK_B32_dpp8_gfx12:
902 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx12:
903 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx12:
904 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx12:
905
906 case AMDGPU::V_CNDMASK_B32_e32_gfx6_gfx7:
907 case AMDGPU::V_CNDMASK_B32_e32_vi:
908 if ((int)OpNo == AMDGPU::getNamedOperandIdx(MI->getOpcode(),
909 AMDGPU::OpName::src1))
910 printDefaultVccOperand(OpNo == 0, STI, O);
911 break;
912 }
913
914 if (Desc.TSFlags & SIInstrFlags::MTBUF) {
915 int SOffsetIdx =
916 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::soffset);
917 assert(SOffsetIdx != -1);
918 if ((int)OpNo == SOffsetIdx)
919 printSymbolicFormat(MI, STI, O);
920 }
921}
922
923void AMDGPUInstPrinter::printOperandAndFPInputMods(const MCInst *MI,
924 unsigned OpNo,
925 const MCSubtargetInfo &STI,
926 raw_ostream &O) {
927 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
928 if (needsImpliedVcc(Desc, OpNo))
929 printDefaultVccOperand(true, STI, O);
930
931 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
932
933 // Use 'neg(...)' instead of '-' to avoid ambiguity.
934 // This is important for integer literals because
935 // -1 is not the same value as neg(1).
936 bool NegMnemo = false;
937
938 if (InputModifiers & SISrcMods::NEG) {
939 if (OpNo + 1 < MI->getNumOperands() &&
940 (InputModifiers & SISrcMods::ABS) == 0) {
941 const MCOperand &Op = MI->getOperand(OpNo + 1);
942 NegMnemo = Op.isImm();
943 }
944 if (NegMnemo) {
945 O << "neg(";
946 } else {
947 O << '-';
948 }
949 }
950
951 if (InputModifiers & SISrcMods::ABS)
952 O << '|';
953 printRegularOperand(MI, OpNo + 1, STI, O);
954 if (InputModifiers & SISrcMods::ABS)
955 O << '|';
956
957 if (NegMnemo) {
958 O << ')';
959 }
960
961 // Print default vcc/vcc_lo operand of VOP2b.
962 switch (MI->getOpcode()) {
963 default:
964 break;
965
966 case AMDGPU::V_CNDMASK_B32_sdwa_gfx10:
967 case AMDGPU::V_CNDMASK_B32_dpp_gfx10:
968 case AMDGPU::V_CNDMASK_B32_dpp_gfx11:
969 if ((int)OpNo + 1 ==
970 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::src1))
971 printDefaultVccOperand(OpNo == 0, STI, O);
972 break;
973 }
974}
975
976void AMDGPUInstPrinter::printOperandAndIntInputMods(const MCInst *MI,
977 unsigned OpNo,
978 const MCSubtargetInfo &STI,
979 raw_ostream &O) {
980 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
981 if (needsImpliedVcc(Desc, OpNo))
982 printDefaultVccOperand(true, STI, O);
983
984 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
985 if (InputModifiers & SISrcMods::SEXT)
986 O << "sext(";
987 printRegularOperand(MI, OpNo + 1, STI, O);
988 if (InputModifiers & SISrcMods::SEXT)
989 O << ')';
990
991 // Print default vcc/vcc_lo operand of VOP2b.
992 switch (MI->getOpcode()) {
993 default: break;
994
995 case AMDGPU::V_ADD_CO_CI_U32_sdwa_gfx10:
996 case AMDGPU::V_SUB_CO_CI_U32_sdwa_gfx10:
997 case AMDGPU::V_SUBREV_CO_CI_U32_sdwa_gfx10:
998 if ((int)OpNo + 1 == AMDGPU::getNamedOperandIdx(MI->getOpcode(),
999 AMDGPU::OpName::src1))
1000 printDefaultVccOperand(OpNo == 0, STI, O);
1001 break;
1002 }
1003}
1004
1005void AMDGPUInstPrinter::printDPP8(const MCInst *MI, unsigned OpNo,
1006 const MCSubtargetInfo &STI,
1007 raw_ostream &O) {
1008 if (!AMDGPU::isGFX10Plus(STI))
1009 llvm_unreachable("dpp8 is not supported on ASICs earlier than GFX10");
1010
1011 unsigned Imm = MI->getOperand(OpNo).getImm();
1012 O << "dpp8:[" << formatDec(Imm & 0x7);
1013 for (size_t i = 1; i < 8; ++i) {
1014 O << ',' << formatDec((Imm >> (3 * i)) & 0x7);
1015 }
1016 O << ']';
1017}
1018
1019void AMDGPUInstPrinter::printDPPCtrl(const MCInst *MI, unsigned OpNo,
1020 const MCSubtargetInfo &STI,
1021 raw_ostream &O) {
1022 using namespace AMDGPU::DPP;
1023
1024 unsigned Imm = MI->getOperand(OpNo).getImm();
1025 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
1026
1028 AMDGPU::isDPALU_DPP(Desc, STI)) {
1029 O << " /* DP ALU dpp only supports "
1030 << (isGFX12(STI) ? "row_share" : "row_newbcast") << " */";
1031 return;
1032 }
1033 if (Imm <= DppCtrl::QUAD_PERM_LAST) {
1034 O << "quad_perm:[";
1035 O << formatDec(Imm & 0x3) << ',';
1036 O << formatDec((Imm & 0xc) >> 2) << ',';
1037 O << formatDec((Imm & 0x30) >> 4) << ',';
1038 O << formatDec((Imm & 0xc0) >> 6) << ']';
1039 } else if ((Imm >= DppCtrl::ROW_SHL_FIRST) &&
1040 (Imm <= DppCtrl::ROW_SHL_LAST)) {
1041 O << "row_shl:" << formatDec(Imm - DppCtrl::ROW_SHL0);
1042 } else if ((Imm >= DppCtrl::ROW_SHR_FIRST) &&
1043 (Imm <= DppCtrl::ROW_SHR_LAST)) {
1044 O << "row_shr:" << formatDec(Imm - DppCtrl::ROW_SHR0);
1045 } else if ((Imm >= DppCtrl::ROW_ROR_FIRST) &&
1046 (Imm <= DppCtrl::ROW_ROR_LAST)) {
1047 O << "row_ror:" << formatDec(Imm - DppCtrl::ROW_ROR0);
1048 } else if (Imm == DppCtrl::WAVE_SHL1) {
1049 if (AMDGPU::isGFX10Plus(STI)) {
1050 O << "/* wave_shl is not supported starting from GFX10 */";
1051 return;
1052 }
1053 O << "wave_shl:1";
1054 } else if (Imm == DppCtrl::WAVE_ROL1) {
1055 if (AMDGPU::isGFX10Plus(STI)) {
1056 O << "/* wave_rol is not supported starting from GFX10 */";
1057 return;
1058 }
1059 O << "wave_rol:1";
1060 } else if (Imm == DppCtrl::WAVE_SHR1) {
1061 if (AMDGPU::isGFX10Plus(STI)) {
1062 O << "/* wave_shr is not supported starting from GFX10 */";
1063 return;
1064 }
1065 O << "wave_shr:1";
1066 } else if (Imm == DppCtrl::WAVE_ROR1) {
1067 if (AMDGPU::isGFX10Plus(STI)) {
1068 O << "/* wave_ror is not supported starting from GFX10 */";
1069 return;
1070 }
1071 O << "wave_ror:1";
1072 } else if (Imm == DppCtrl::ROW_MIRROR) {
1073 O << "row_mirror";
1074 } else if (Imm == DppCtrl::ROW_HALF_MIRROR) {
1075 O << "row_half_mirror";
1076 } else if (Imm == DppCtrl::BCAST15) {
1077 if (AMDGPU::isGFX10Plus(STI)) {
1078 O << "/* row_bcast is not supported starting from GFX10 */";
1079 return;
1080 }
1081 O << "row_bcast:15";
1082 } else if (Imm == DppCtrl::BCAST31) {
1083 if (AMDGPU::isGFX10Plus(STI)) {
1084 O << "/* row_bcast is not supported starting from GFX10 */";
1085 return;
1086 }
1087 O << "row_bcast:31";
1088 } else if ((Imm >= DppCtrl::ROW_SHARE_FIRST) &&
1089 (Imm <= DppCtrl::ROW_SHARE_LAST)) {
1090 if (AMDGPU::isGFX90A(STI)) {
1091 O << "row_newbcast:";
1092 } else if (AMDGPU::isGFX10Plus(STI)) {
1093 O << "row_share:";
1094 } else {
1095 O << " /* row_newbcast/row_share is not supported on ASICs earlier "
1096 "than GFX90A/GFX10 */";
1097 return;
1098 }
1099 O << formatDec(Imm - DppCtrl::ROW_SHARE_FIRST);
1100 } else if ((Imm >= DppCtrl::ROW_XMASK_FIRST) &&
1101 (Imm <= DppCtrl::ROW_XMASK_LAST)) {
1102 if (!AMDGPU::isGFX10Plus(STI)) {
1103 O << "/* row_xmask is not supported on ASICs earlier than GFX10 */";
1104 return;
1105 }
1106 O << "row_xmask:" << formatDec(Imm - DppCtrl::ROW_XMASK_FIRST);
1107 } else {
1108 O << "/* Invalid dpp_ctrl value */";
1109 }
1110}
1111
1112void AMDGPUInstPrinter::printDppBoundCtrl(const MCInst *MI, unsigned OpNo,
1113 const MCSubtargetInfo &STI,
1114 raw_ostream &O) {
1115 unsigned Imm = MI->getOperand(OpNo).getImm();
1116 if (Imm) {
1117 O << " bound_ctrl:1";
1118 }
1119}
1120
1121void AMDGPUInstPrinter::printDppFI(const MCInst *MI, unsigned OpNo,
1122 const MCSubtargetInfo &STI, raw_ostream &O) {
1123 using namespace llvm::AMDGPU::DPP;
1124 unsigned Imm = MI->getOperand(OpNo).getImm();
1125 if (Imm == DPP_FI_1 || Imm == DPP8_FI_1) {
1126 O << " fi:1";
1127 }
1128}
1129
1130void AMDGPUInstPrinter::printSDWASel(const MCInst *MI, unsigned OpNo,
1131 raw_ostream &O) {
1132 using namespace llvm::AMDGPU::SDWA;
1133
1134 unsigned Imm = MI->getOperand(OpNo).getImm();
1135 switch (Imm) {
1136 case SdwaSel::BYTE_0: O << "BYTE_0"; break;
1137 case SdwaSel::BYTE_1: O << "BYTE_1"; break;
1138 case SdwaSel::BYTE_2: O << "BYTE_2"; break;
1139 case SdwaSel::BYTE_3: O << "BYTE_3"; break;
1140 case SdwaSel::WORD_0: O << "WORD_0"; break;
1141 case SdwaSel::WORD_1: O << "WORD_1"; break;
1142 case SdwaSel::DWORD: O << "DWORD"; break;
1143 default: llvm_unreachable("Invalid SDWA data select operand");
1144 }
1145}
1146
1147void AMDGPUInstPrinter::printSDWADstSel(const MCInst *MI, unsigned OpNo,
1148 const MCSubtargetInfo &STI,
1149 raw_ostream &O) {
1150 O << "dst_sel:";
1151 printSDWASel(MI, OpNo, O);
1152}
1153
1154void AMDGPUInstPrinter::printSDWASrc0Sel(const MCInst *MI, unsigned OpNo,
1155 const MCSubtargetInfo &STI,
1156 raw_ostream &O) {
1157 O << "src0_sel:";
1158 printSDWASel(MI, OpNo, O);
1159}
1160
1161void AMDGPUInstPrinter::printSDWASrc1Sel(const MCInst *MI, unsigned OpNo,
1162 const MCSubtargetInfo &STI,
1163 raw_ostream &O) {
1164 O << "src1_sel:";
1165 printSDWASel(MI, OpNo, O);
1166}
1167
1168void AMDGPUInstPrinter::printSDWADstUnused(const MCInst *MI, unsigned OpNo,
1169 const MCSubtargetInfo &STI,
1170 raw_ostream &O) {
1171 using namespace llvm::AMDGPU::SDWA;
1172
1173 O << "dst_unused:";
1174 unsigned Imm = MI->getOperand(OpNo).getImm();
1175 switch (Imm) {
1176 case DstUnused::UNUSED_PAD: O << "UNUSED_PAD"; break;
1177 case DstUnused::UNUSED_SEXT: O << "UNUSED_SEXT"; break;
1178 case DstUnused::UNUSED_PRESERVE: O << "UNUSED_PRESERVE"; break;
1179 default: llvm_unreachable("Invalid SDWA dest_unused operand");
1180 }
1181}
1182
1183void AMDGPUInstPrinter::printExpSrcN(const MCInst *MI, unsigned OpNo,
1184 const MCSubtargetInfo &STI, raw_ostream &O,
1185 unsigned N) {
1186 unsigned Opc = MI->getOpcode();
1187 int EnIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::en);
1188 unsigned En = MI->getOperand(EnIdx).getImm();
1189
1190 int ComprIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::compr);
1191
1192 // If compr is set, print as src0, src0, src1, src1
1193 if (MI->getOperand(ComprIdx).getImm())
1194 OpNo = OpNo - N + N / 2;
1195
1196 if (En & (1 << N))
1197 printRegOperand(MI->getOperand(OpNo).getReg(), Opc, OpNo, O, MRI);
1198 else
1199 O << "off";
1200}
1201
1202void AMDGPUInstPrinter::printExpSrc0(const MCInst *MI, unsigned OpNo,
1203 const MCSubtargetInfo &STI,
1204 raw_ostream &O) {
1205 printExpSrcN(MI, OpNo, STI, O, 0);
1206}
1207
1208void AMDGPUInstPrinter::printExpSrc1(const MCInst *MI, unsigned OpNo,
1209 const MCSubtargetInfo &STI,
1210 raw_ostream &O) {
1211 printExpSrcN(MI, OpNo, STI, O, 1);
1212}
1213
1214void AMDGPUInstPrinter::printExpSrc2(const MCInst *MI, unsigned OpNo,
1215 const MCSubtargetInfo &STI,
1216 raw_ostream &O) {
1217 printExpSrcN(MI, OpNo, STI, O, 2);
1218}
1219
1220void AMDGPUInstPrinter::printExpSrc3(const MCInst *MI, unsigned OpNo,
1221 const MCSubtargetInfo &STI,
1222 raw_ostream &O) {
1223 printExpSrcN(MI, OpNo, STI, O, 3);
1224}
1225
1226void AMDGPUInstPrinter::printExpTgt(const MCInst *MI, unsigned OpNo,
1227 const MCSubtargetInfo &STI,
1228 raw_ostream &O) {
1229 using namespace llvm::AMDGPU::Exp;
1230
1231 // This is really a 6 bit field.
1232 unsigned Id = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1);
1233
1234 int Index;
1235 StringRef TgtName;
1236 if (getTgtName(Id, TgtName, Index) && isSupportedTgtId(Id, STI)) {
1237 O << ' ' << TgtName;
1238 if (Index >= 0)
1239 O << Index;
1240 } else {
1241 O << " invalid_target_" << Id;
1242 }
1243}
1244
1245static bool allOpsDefaultValue(const int* Ops, int NumOps, int Mod,
1246 bool IsPacked, bool HasDstSel) {
1247 int DefaultValue = IsPacked && (Mod == SISrcMods::OP_SEL_1);
1248
1249 for (int I = 0; I < NumOps; ++I) {
1250 if (!!(Ops[I] & Mod) != DefaultValue)
1251 return false;
1252 }
1253
1254 if (HasDstSel && (Ops[0] & SISrcMods::DST_OP_SEL) != 0)
1255 return false;
1256
1257 return true;
1258}
1259
1260void AMDGPUInstPrinter::printPackedModifier(const MCInst *MI,
1261 StringRef Name,
1262 unsigned Mod,
1263 raw_ostream &O) {
1264 unsigned Opc = MI->getOpcode();
1265 int NumOps = 0;
1266 int Ops[3];
1267
1268 std::pair<AMDGPU::OpName, AMDGPU::OpName> MOps[] = {
1269 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src0},
1270 {AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src1},
1271 {AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::src2}};
1272 int DefaultValue = (Mod == SISrcMods::OP_SEL_1);
1273
1274 for (auto [SrcMod, Src] : MOps) {
1275 if (!AMDGPU::hasNamedOperand(Opc, Src))
1276 break;
1277
1278 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, SrcMod);
1279 Ops[NumOps++] =
1280 (ModIdx != -1) ? MI->getOperand(ModIdx).getImm() : DefaultValue;
1281 }
1282
1283 const bool HasDst =
1284 (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst) != -1) ||
1285 (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst) != -1);
1286
1287 // Print three values of neg/opsel for wmma instructions (prints 0 when there
1288 // is no src_modifier operand instead of not printing anything).
1289 if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsSWMMAC ||
1290 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsWMMA) {
1291 NumOps = 0;
1292 int DefaultValue = Mod == SISrcMods::OP_SEL_1;
1293 for (AMDGPU::OpName OpName :
1294 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
1295 AMDGPU::OpName::src2_modifiers}) {
1296 int Idx = AMDGPU::getNamedOperandIdx(Opc, OpName);
1297 if (Idx != -1)
1298 Ops[NumOps++] = MI->getOperand(Idx).getImm();
1299 else
1300 Ops[NumOps++] = DefaultValue;
1301 }
1302 }
1303
1304 const bool HasDstSel =
1305 HasDst && NumOps > 0 && Mod == SISrcMods::OP_SEL_0 &&
1306 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3_OPSEL;
1307
1308 const bool IsPacked =
1309 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsPacked;
1310
1311 if (allOpsDefaultValue(Ops, NumOps, Mod, IsPacked, HasDstSel))
1312 return;
1313
1314 O << Name;
1315 for (int I = 0; I < NumOps; ++I) {
1316 if (I != 0)
1317 O << ',';
1318
1319 O << !!(Ops[I] & Mod);
1320 }
1321
1322 if (HasDstSel) {
1323 O << ',' << !!(Ops[0] & SISrcMods::DST_OP_SEL);
1324 }
1325
1326 O << ']';
1327}
1328
1329void AMDGPUInstPrinter::printOpSel(const MCInst *MI, unsigned,
1330 const MCSubtargetInfo &STI,
1331 raw_ostream &O) {
1332 unsigned Opc = MI->getOpcode();
1334 auto SrcMod =
1335 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
1336 unsigned Mod = MI->getOperand(SrcMod).getImm();
1337 unsigned Index0 = !!(Mod & SISrcMods::OP_SEL_0);
1338 unsigned Index1 = !!(Mod & SISrcMods::OP_SEL_1);
1339 if (Index0 || Index1)
1340 O << " op_sel:[" << Index0 << ',' << Index1 << ']';
1341 return;
1342 }
1343 if (isPermlane16(Opc)) {
1344 auto FIN = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
1345 auto BCN = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1_modifiers);
1346 unsigned FI = !!(MI->getOperand(FIN).getImm() & SISrcMods::OP_SEL_0);
1347 unsigned BC = !!(MI->getOperand(BCN).getImm() & SISrcMods::OP_SEL_0);
1348 if (FI || BC)
1349 O << " op_sel:[" << FI << ',' << BC << ']';
1350 return;
1351 }
1352
1353 printPackedModifier(MI, " op_sel:[", SISrcMods::OP_SEL_0, O);
1354}
1355
1356void AMDGPUInstPrinter::printOpSelHi(const MCInst *MI, unsigned OpNo,
1357 const MCSubtargetInfo &STI,
1358 raw_ostream &O) {
1359 printPackedModifier(MI, " op_sel_hi:[", SISrcMods::OP_SEL_1, O);
1360}
1361
1362void AMDGPUInstPrinter::printNegLo(const MCInst *MI, unsigned OpNo,
1363 const MCSubtargetInfo &STI,
1364 raw_ostream &O) {
1365 printPackedModifier(MI, " neg_lo:[", SISrcMods::NEG, O);
1366}
1367
1368void AMDGPUInstPrinter::printNegHi(const MCInst *MI, unsigned OpNo,
1369 const MCSubtargetInfo &STI,
1370 raw_ostream &O) {
1371 printPackedModifier(MI, " neg_hi:[", SISrcMods::NEG_HI, O);
1372}
1373
1374void AMDGPUInstPrinter::printIndexKey8bit(const MCInst *MI, unsigned OpNo,
1375 const MCSubtargetInfo &STI,
1376 raw_ostream &O) {
1377 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1378 if (Imm == 0)
1379 return;
1380
1381 O << " index_key:" << Imm;
1382}
1383
1384void AMDGPUInstPrinter::printIndexKey16bit(const MCInst *MI, unsigned OpNo,
1385 const MCSubtargetInfo &STI,
1386 raw_ostream &O) {
1387 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1388 if (Imm == 0)
1389 return;
1390
1391 O << " index_key:" << Imm;
1392}
1393
1394void AMDGPUInstPrinter::printIndexKey32bit(const MCInst *MI, unsigned OpNo,
1395 const MCSubtargetInfo &STI,
1396 raw_ostream &O) {
1397 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1398 if (Imm == 0)
1399 return;
1400
1401 O << " index_key:" << Imm;
1402}
1403
1404void AMDGPUInstPrinter::printMatrixFMT(const MCInst *MI, unsigned OpNo,
1405 const MCSubtargetInfo &STI,
1406 raw_ostream &O, char AorB) {
1407 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1408 if (Imm == 0)
1409 return;
1410
1411 O << " matrix_" << AorB << "_fmt:";
1412 switch (Imm) {
1413 default:
1414 O << Imm;
1415 break;
1416 case WMMA::MatrixFMT::MATRIX_FMT_FP8:
1417 O << "MATRIX_FMT_FP8";
1418 break;
1419 case WMMA::MatrixFMT::MATRIX_FMT_BF8:
1420 O << "MATRIX_FMT_BF8";
1421 break;
1422 case WMMA::MatrixFMT::MATRIX_FMT_FP6:
1423 O << "MATRIX_FMT_FP6";
1424 break;
1425 case WMMA::MatrixFMT::MATRIX_FMT_BF6:
1426 O << "MATRIX_FMT_BF6";
1427 break;
1428 case WMMA::MatrixFMT::MATRIX_FMT_FP4:
1429 O << "MATRIX_FMT_FP4";
1430 break;
1431 }
1432}
1433
1434void AMDGPUInstPrinter::printMatrixAFMT(const MCInst *MI, unsigned OpNo,
1435 const MCSubtargetInfo &STI,
1436 raw_ostream &O) {
1437 printMatrixFMT(MI, OpNo, STI, O, 'a');
1438}
1439
1440void AMDGPUInstPrinter::printMatrixBFMT(const MCInst *MI, unsigned OpNo,
1441 const MCSubtargetInfo &STI,
1442 raw_ostream &O) {
1443 printMatrixFMT(MI, OpNo, STI, O, 'b');
1444}
1445
1446void AMDGPUInstPrinter::printMatrixScale(const MCInst *MI, unsigned OpNo,
1447 const MCSubtargetInfo &STI,
1448 raw_ostream &O, char AorB) {
1449 auto Imm = MI->getOperand(OpNo).getImm() & 1;
1450 if (Imm == 0)
1451 return;
1452
1453 O << " matrix_" << AorB << "_scale:";
1454 switch (Imm) {
1455 default:
1456 O << Imm;
1457 break;
1458 case WMMA::MatrixScale::MATRIX_SCALE_ROW0:
1459 O << "MATRIX_SCALE_ROW0";
1460 break;
1461 case WMMA::MatrixScale::MATRIX_SCALE_ROW1:
1462 O << "MATRIX_SCALE_ROW1";
1463 break;
1464 }
1465}
1466
1467void AMDGPUInstPrinter::printMatrixAScale(const MCInst *MI, unsigned OpNo,
1468 const MCSubtargetInfo &STI,
1469 raw_ostream &O) {
1470 printMatrixScale(MI, OpNo, STI, O, 'a');
1471}
1472
1473void AMDGPUInstPrinter::printMatrixBScale(const MCInst *MI, unsigned OpNo,
1474 const MCSubtargetInfo &STI,
1475 raw_ostream &O) {
1476 printMatrixScale(MI, OpNo, STI, O, 'b');
1477}
1478
1479void AMDGPUInstPrinter::printMatrixScaleFmt(const MCInst *MI, unsigned OpNo,
1480 const MCSubtargetInfo &STI,
1481 raw_ostream &O, char AorB) {
1482 auto Imm = MI->getOperand(OpNo).getImm() & 3;
1483 if (Imm == 0)
1484 return;
1485
1486 O << " matrix_" << AorB << "_scale_fmt:";
1487 switch (Imm) {
1488 default:
1489 O << Imm;
1490 break;
1491 case WMMA::MatrixScaleFmt::MATRIX_SCALE_FMT_E8:
1492 O << "MATRIX_SCALE_FMT_E8";
1493 break;
1494 case WMMA::MatrixScaleFmt::MATRIX_SCALE_FMT_E5M3:
1495 O << "MATRIX_SCALE_FMT_E5M3";
1496 break;
1497 case WMMA::MatrixScaleFmt::MATRIX_SCALE_FMT_E4M3:
1498 O << "MATRIX_SCALE_FMT_E4M3";
1499 break;
1500 }
1501}
1502
1503void AMDGPUInstPrinter::printMatrixAScaleFmt(const MCInst *MI, unsigned OpNo,
1504 const MCSubtargetInfo &STI,
1505 raw_ostream &O) {
1506 printMatrixScaleFmt(MI, OpNo, STI, O, 'a');
1507}
1508
1509void AMDGPUInstPrinter::printMatrixBScaleFmt(const MCInst *MI, unsigned OpNo,
1510 const MCSubtargetInfo &STI,
1511 raw_ostream &O) {
1512 printMatrixScaleFmt(MI, OpNo, STI, O, 'b');
1513}
1514
1515void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
1516 const MCSubtargetInfo &STI,
1517 raw_ostream &O) {
1518 unsigned Imm = MI->getOperand(OpNum).getImm();
1519 switch (Imm) {
1520 case 0:
1521 O << "p10";
1522 break;
1523 case 1:
1524 O << "p20";
1525 break;
1526 case 2:
1527 O << "p0";
1528 break;
1529 default:
1530 O << "invalid_param_" << Imm;
1531 }
1532}
1533
1534void AMDGPUInstPrinter::printInterpAttr(const MCInst *MI, unsigned OpNum,
1535 const MCSubtargetInfo &STI,
1536 raw_ostream &O) {
1537 unsigned Attr = MI->getOperand(OpNum).getImm();
1538 O << "attr" << Attr;
1539}
1540
1541void AMDGPUInstPrinter::printInterpAttrChan(const MCInst *MI, unsigned OpNum,
1542 const MCSubtargetInfo &STI,
1543 raw_ostream &O) {
1544 unsigned Chan = MI->getOperand(OpNum).getImm();
1545 O << '.' << "xyzw"[Chan & 0x3];
1546}
1547
1548void AMDGPUInstPrinter::printGPRIdxMode(const MCInst *MI, unsigned OpNo,
1549 const MCSubtargetInfo &STI,
1550 raw_ostream &O) {
1551 using namespace llvm::AMDGPU::VGPRIndexMode;
1552 unsigned Val = MI->getOperand(OpNo).getImm();
1553
1554 if ((Val & ~ENABLE_MASK) != 0) {
1555 O << formatHex(static_cast<uint64_t>(Val));
1556 } else {
1557 O << "gpr_idx(";
1558 bool NeedComma = false;
1559 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
1560 if (Val & (1 << ModeId)) {
1561 if (NeedComma)
1562 O << ',';
1563 O << IdSymbolic[ModeId];
1564 NeedComma = true;
1565 }
1566 }
1567 O << ')';
1568 }
1569}
1570
1571void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
1572 const MCSubtargetInfo &STI,
1573 raw_ostream &O) {
1574 printRegularOperand(MI, OpNo, STI, O);
1575 O << ", ";
1576 printRegularOperand(MI, OpNo + 1, STI, O);
1577}
1578
1579void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
1580 raw_ostream &O, StringRef Asm,
1582 const MCOperand &Op = MI->getOperand(OpNo);
1583 assert(Op.isImm());
1584 if (Op.getImm() == 1) {
1585 O << Asm;
1586 } else {
1587 O << Default;
1588 }
1589}
1590
1591void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
1592 raw_ostream &O, char Asm) {
1593 const MCOperand &Op = MI->getOperand(OpNo);
1594 assert(Op.isImm());
1595 if (Op.getImm() == 1)
1596 O << Asm;
1597}
1598
1599void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
1600 const MCSubtargetInfo &STI,
1601 raw_ostream &O) {
1602 int Imm = MI->getOperand(OpNo).getImm();
1603 if (Imm == SIOutMods::MUL2)
1604 O << " mul:2";
1605 else if (Imm == SIOutMods::MUL4)
1606 O << " mul:4";
1607 else if (Imm == SIOutMods::DIV2)
1608 O << " div:2";
1609}
1610
1611void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
1612 const MCSubtargetInfo &STI,
1613 raw_ostream &O) {
1614 using namespace llvm::AMDGPU::SendMsg;
1615
1616 const unsigned Imm16 = MI->getOperand(OpNo).getImm();
1617
1618 uint16_t MsgId;
1619 uint16_t OpId;
1621 decodeMsg(Imm16, MsgId, OpId, StreamId, STI);
1622
1623 StringRef MsgName = getMsgName(MsgId, STI);
1624
1625 if (!MsgName.empty() && isValidMsgOp(MsgId, OpId, STI) &&
1626 isValidMsgStream(MsgId, OpId, StreamId, STI)) {
1627 O << "sendmsg(" << MsgName;
1628 if (msgRequiresOp(MsgId, STI)) {
1629 O << ", " << getMsgOpName(MsgId, OpId, STI);
1630 if (msgSupportsStream(MsgId, OpId, STI)) {
1631 O << ", " << StreamId;
1632 }
1633 }
1634 O << ')';
1635 } else if (encodeMsg(MsgId, OpId, StreamId) == Imm16) {
1636 O << "sendmsg(" << MsgId << ", " << OpId << ", " << StreamId << ')';
1637 } else {
1638 O << Imm16; // Unknown imm16 code.
1639 }
1640}
1641
1642static void printSwizzleBitmask(const uint16_t AndMask,
1643 const uint16_t OrMask,
1644 const uint16_t XorMask,
1645 raw_ostream &O) {
1646 using namespace llvm::AMDGPU::Swizzle;
1647
1648 uint16_t Probe0 = ((0 & AndMask) | OrMask) ^ XorMask;
1649 uint16_t Probe1 = ((BITMASK_MASK & AndMask) | OrMask) ^ XorMask;
1650
1651 O << "\"";
1652
1653 for (unsigned Mask = 1 << (BITMASK_WIDTH - 1); Mask > 0; Mask >>= 1) {
1654 uint16_t p0 = Probe0 & Mask;
1655 uint16_t p1 = Probe1 & Mask;
1656
1657 if (p0 == p1) {
1658 if (p0 == 0) {
1659 O << "0";
1660 } else {
1661 O << "1";
1662 }
1663 } else {
1664 if (p0 == 0) {
1665 O << "p";
1666 } else {
1667 O << "i";
1668 }
1669 }
1670 }
1671
1672 O << "\"";
1673}
1674
1675void AMDGPUInstPrinter::printSwizzle(const MCInst *MI, unsigned OpNo,
1676 const MCSubtargetInfo &STI,
1677 raw_ostream &O) {
1678 using namespace llvm::AMDGPU::Swizzle;
1679
1680 uint16_t Imm = MI->getOperand(OpNo).getImm();
1681 if (Imm == 0) {
1682 return;
1683 }
1684
1685 O << " offset:";
1686
1687 // Rotate and FFT modes
1688 if (Imm >= ROTATE_MODE_LO && AMDGPU::isGFX9Plus(STI)) {
1689 if (Imm >= FFT_MODE_LO) {
1690 O << "swizzle(" << IdSymbolic[ID_FFT] << ',' << (Imm & FFT_SWIZZLE_MASK)
1691 << ')';
1692 } else if (Imm >= ROTATE_MODE_LO) {
1693 O << "swizzle(" << IdSymbolic[ID_ROTATE] << ','
1694 << ((Imm >> ROTATE_DIR_SHIFT) & ROTATE_DIR_MASK) << ','
1695 << ((Imm >> ROTATE_SIZE_SHIFT) & ROTATE_SIZE_MASK) << ')';
1696 }
1697 return;
1698 }
1699
1700 // Basic mode
1702 O << "swizzle(" << IdSymbolic[ID_QUAD_PERM];
1703 for (unsigned I = 0; I < LANE_NUM; ++I) {
1704 O << ",";
1705 O << formatDec(Imm & LANE_MASK);
1706 Imm >>= LANE_SHIFT;
1707 }
1708 O << ")";
1709
1710 } else if ((Imm & BITMASK_PERM_ENC_MASK) == BITMASK_PERM_ENC) {
1711
1712 uint16_t AndMask = (Imm >> BITMASK_AND_SHIFT) & BITMASK_MASK;
1713 uint16_t OrMask = (Imm >> BITMASK_OR_SHIFT) & BITMASK_MASK;
1714 uint16_t XorMask = (Imm >> BITMASK_XOR_SHIFT) & BITMASK_MASK;
1715
1716 if (AndMask == BITMASK_MAX && OrMask == 0 && llvm::popcount(XorMask) == 1) {
1717
1718 O << "swizzle(" << IdSymbolic[ID_SWAP];
1719 O << ",";
1720 O << formatDec(XorMask);
1721 O << ")";
1722
1723 } else if (AndMask == BITMASK_MAX && OrMask == 0 && XorMask > 0 &&
1724 isPowerOf2_64(XorMask + 1)) {
1725
1726 O << "swizzle(" << IdSymbolic[ID_REVERSE];
1727 O << ",";
1728 O << formatDec(XorMask + 1);
1729 O << ")";
1730
1731 } else {
1732
1733 uint16_t GroupSize = BITMASK_MAX - AndMask + 1;
1734 if (GroupSize > 1 &&
1735 isPowerOf2_64(GroupSize) &&
1736 OrMask < GroupSize &&
1737 XorMask == 0) {
1738
1739 O << "swizzle(" << IdSymbolic[ID_BROADCAST];
1740 O << ",";
1741 O << formatDec(GroupSize);
1742 O << ",";
1743 O << formatDec(OrMask);
1744 O << ")";
1745
1746 } else {
1747 O << "swizzle(" << IdSymbolic[ID_BITMASK_PERM];
1748 O << ",";
1749 printSwizzleBitmask(AndMask, OrMask, XorMask, O);
1750 O << ")";
1751 }
1752 }
1753 } else {
1754 printU16ImmDecOperand(MI, OpNo, O);
1755 }
1756}
1757
1758void AMDGPUInstPrinter::printSWaitCnt(const MCInst *MI, unsigned OpNo,
1759 const MCSubtargetInfo &STI,
1760 raw_ostream &O) {
1762
1763 unsigned SImm16 = MI->getOperand(OpNo).getImm();
1764 unsigned Vmcnt, Expcnt, Lgkmcnt;
1765 decodeWaitcnt(ISA, SImm16, Vmcnt, Expcnt, Lgkmcnt);
1766
1767 bool IsDefaultVmcnt = Vmcnt == getVmcntBitMask(ISA);
1768 bool IsDefaultExpcnt = Expcnt == getExpcntBitMask(ISA);
1769 bool IsDefaultLgkmcnt = Lgkmcnt == getLgkmcntBitMask(ISA);
1770 bool PrintAll = IsDefaultVmcnt && IsDefaultExpcnt && IsDefaultLgkmcnt;
1771
1772 bool NeedSpace = false;
1773
1774 if (!IsDefaultVmcnt || PrintAll) {
1775 O << "vmcnt(" << Vmcnt << ')';
1776 NeedSpace = true;
1777 }
1778
1779 if (!IsDefaultExpcnt || PrintAll) {
1780 if (NeedSpace)
1781 O << ' ';
1782 O << "expcnt(" << Expcnt << ')';
1783 NeedSpace = true;
1784 }
1785
1786 if (!IsDefaultLgkmcnt || PrintAll) {
1787 if (NeedSpace)
1788 O << ' ';
1789 O << "lgkmcnt(" << Lgkmcnt << ')';
1790 }
1791}
1792
1793void AMDGPUInstPrinter::printDepCtr(const MCInst *MI, unsigned OpNo,
1794 const MCSubtargetInfo &STI,
1795 raw_ostream &O) {
1796 using namespace llvm::AMDGPU::DepCtr;
1797
1798 uint64_t Imm16 = MI->getOperand(OpNo).getImm() & 0xffff;
1799
1800 bool HasNonDefaultVal = false;
1801 if (isSymbolicDepCtrEncoding(Imm16, HasNonDefaultVal, STI)) {
1802 int Id = 0;
1803 StringRef Name;
1804 unsigned Val;
1805 bool IsDefault;
1806 bool NeedSpace = false;
1807 while (decodeDepCtr(Imm16, Id, Name, Val, IsDefault, STI)) {
1808 if (!IsDefault || !HasNonDefaultVal) {
1809 if (NeedSpace)
1810 O << ' ';
1811 O << Name << '(' << Val << ')';
1812 NeedSpace = true;
1813 }
1814 }
1815 } else {
1816 O << formatHex(Imm16);
1817 }
1818}
1819
1821 const MCSubtargetInfo &STI,
1822 raw_ostream &O) {
1823 const char *BadInstId = "/* invalid instid value */";
1824 static const std::array<const char *, 12> InstIds = {
1825 "NO_DEP", "VALU_DEP_1", "VALU_DEP_2",
1826 "VALU_DEP_3", "VALU_DEP_4", "TRANS32_DEP_1",
1827 "TRANS32_DEP_2", "TRANS32_DEP_3", "FMA_ACCUM_CYCLE_1",
1828 "SALU_CYCLE_1", "SALU_CYCLE_2", "SALU_CYCLE_3"};
1829
1830 const char *BadInstSkip = "/* invalid instskip value */";
1831 static const std::array<const char *, 6> InstSkips = {
1832 "SAME", "NEXT", "SKIP_1", "SKIP_2", "SKIP_3", "SKIP_4"};
1833
1834 unsigned SImm16 = MI->getOperand(OpNo).getImm();
1835 const char *Prefix = "";
1836
1837 unsigned Value = SImm16 & 0xF;
1838 if (Value) {
1839 const char *Name = Value < InstIds.size() ? InstIds[Value] : BadInstId;
1840 O << Prefix << "instid0(" << Name << ')';
1841 Prefix = " | ";
1842 }
1843
1844 Value = (SImm16 >> 4) & 7;
1845 if (Value) {
1846 const char *Name =
1847 Value < InstSkips.size() ? InstSkips[Value] : BadInstSkip;
1848 O << Prefix << "instskip(" << Name << ')';
1849 Prefix = " | ";
1850 }
1851
1852 Value = (SImm16 >> 7) & 0xF;
1853 if (Value) {
1854 const char *Name = Value < InstIds.size() ? InstIds[Value] : BadInstId;
1855 O << Prefix << "instid1(" << Name << ')';
1856 Prefix = " | ";
1857 }
1858
1859 if (!*Prefix)
1860 O << "0";
1861}
1862
1863void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
1864 const MCSubtargetInfo &STI, raw_ostream &O) {
1865 using namespace llvm::AMDGPU::Hwreg;
1866 unsigned Val = MI->getOperand(OpNo).getImm();
1867 auto [Id, Offset, Width] = HwregEncoding::decode(Val);
1868 StringRef HwRegName = getHwreg(Id, STI);
1869
1870 O << "hwreg(";
1871 if (!HwRegName.empty()) {
1872 O << HwRegName;
1873 } else {
1874 O << Id;
1875 }
1877 O << ", " << Offset << ", " << Width;
1878 O << ')';
1879}
1880
1881void AMDGPUInstPrinter::printEndpgm(const MCInst *MI, unsigned OpNo,
1882 const MCSubtargetInfo &STI,
1883 raw_ostream &O) {
1884 uint16_t Imm = MI->getOperand(OpNo).getImm();
1885 if (Imm == 0) {
1886 return;
1887 }
1888
1889 O << ' ' << formatDec(Imm);
1890}
1891
1892void AMDGPUInstPrinter::printNamedInt(const MCInst *MI, unsigned OpNo,
1893 const MCSubtargetInfo &STI,
1894 raw_ostream &O, StringRef Prefix,
1895 bool PrintInHex, bool AlwaysPrint) {
1896 int64_t V = MI->getOperand(OpNo).getImm();
1897 if (AlwaysPrint || V != 0)
1898 O << ' ' << Prefix << ':' << (PrintInHex ? formatHex(V) : formatDec(V));
1899}
1900
1901void AMDGPUInstPrinter::printBitOp3(const MCInst *MI, unsigned OpNo,
1902 const MCSubtargetInfo &STI,
1903 raw_ostream &O) {
1904 uint8_t Imm = MI->getOperand(OpNo).getImm();
1905 if (!Imm)
1906 return;
1907
1908 O << " bitop3:";
1909 if (Imm <= 10)
1910 O << formatDec(Imm);
1911 else
1912 O << formatHex(static_cast<uint64_t>(Imm));
1913}
1914
1915void AMDGPUInstPrinter::printScaleSel(const MCInst *MI, unsigned OpNo,
1916 const MCSubtargetInfo &STI,
1917 raw_ostream &O) {
1918 uint8_t Imm = MI->getOperand(OpNo).getImm();
1919 if (!Imm)
1920 return;
1921
1922 O << " scale_sel:" << formatDec(Imm);
1923}
1924
1925#include "AMDGPUGenAsmWriter.inc"
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void printSwizzleBitmask(const uint16_t AndMask, const uint16_t OrMask, const uint16_t XorMask, raw_ostream &O)
static bool printImmediateBFloat16(uint32_t Imm, const MCSubtargetInfo &STI, raw_ostream &O)
static bool allOpsDefaultValue(const int *Ops, int NumOps, int Mod, bool IsPacked, bool HasDstSel)
static MCPhysReg getRegFromMIA(MCPhysReg Reg, unsigned OpNo, const MCInstrDesc &Desc, const MCRegisterInfo &MRI, const AMDGPUMCInstrAnalysis &MIA)
static MCPhysReg getRegForPrinting(MCPhysReg Reg, const MCRegisterInfo &MRI)
static bool printImmediateFP16(uint32_t Imm, const MCSubtargetInfo &STI, raw_ostream &O)
Provides AMDGPU specific target descriptions.
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
void printSwizzle(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printEndpgm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
static const char * getRegisterName(MCRegister Reg)
static void printIfSet(const MCInst *MI, unsigned OpNo, raw_ostream &O, StringRef Asm, StringRef Default="")
void printDepCtr(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printHwreg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printSendMsg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
static void printRegOperand(MCRegister Reg, raw_ostream &O, const MCRegisterInfo &MRI)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
void printInstruction(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O)
void printSWaitCnt(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printOModSI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printSDelayALU(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printExpr(raw_ostream &, const MCExpr &) const
format_object< int64_t > formatHex(int64_t Value) const
const MCInstrInfo & MII
format_object< int64_t > formatDec(int64_t Value) const
Utility functions to print decimal/hexadecimal values.
const MCRegisterInfo & MRI
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
const MCInstrAnalysis * MIA
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:64
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
MCRegisterClass - Base class of TargetRegisterClass.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
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:33
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
StringRef getCPU() const
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:151
LLVM Value Representation.
Definition Value.h:75
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.
bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val, bool &IsDefault, const MCSubtargetInfo &STI)
bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal, const MCSubtargetInfo &STI)
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI)
bool getTgtName(unsigned Id, StringRef &Name, int &Index)
StringRef getHwreg(uint64_t Encoding, const MCSubtargetInfo &STI)
bool isValidUnifiedFormat(unsigned Id, const MCSubtargetInfo &STI)
StringRef getUnifiedFormatName(unsigned Id, const MCSubtargetInfo &STI)
bool isValidDfmtNfmt(unsigned Id, const MCSubtargetInfo &STI)
StringRef getDfmtName(unsigned Id)
StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI)
void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt)
uint64_t encodeMsg(uint64_t MsgId, uint64_t OpId, uint64_t StreamId)
bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI)
void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId, uint16_t &StreamId, const MCSubtargetInfo &STI)
StringRef getMsgName(uint64_t Encoding, const MCSubtargetInfo &STI)
Map from an encoding to the symbolic name for a msg_id immediate.
bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, const MCSubtargetInfo &STI, bool Strict)
StringRef getMsgOpName(int64_t MsgId, uint64_t Encoding, const MCSubtargetInfo &STI)
Map from an encoding to the symbolic name for a sendmsg operation.
bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI, bool Strict)
const char *const IdSymbolic[]
void decodeWaitcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned &Vmcnt, unsigned &Expcnt, unsigned &Lgkmcnt)
Decodes Vmcnt, Expcnt and Lgkmcnt from given Waitcnt for given isa Version, and writes decoded values...
bool isVOPCAsmOnly(unsigned Opc)
unsigned getTemporalHintType(const MCInstrDesc TID)
const MCRegisterClass * getVGPRPhysRegClass(MCPhysReg Reg, const MCRegisterInfo &MRI)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isGFX940(const MCSubtargetInfo &STI)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
bool isSI(const MCSubtargetInfo &STI)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool getVOP3IsSingle(unsigned Opc)
bool getVOP1IsSingle(unsigned Opc)
bool isGFX90A(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isGFX12(const MCSubtargetInfo &STI)
unsigned getVmcntBitMask(const IsaVersion &Version)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getLgkmcntBitMask(const IsaVersion &Version)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCSubtargetInfo &ST)
std::pair< const AMDGPU::OpName *, const AMDGPU::OpName * > getVGPRLoweringOperandTables(const MCInstrDesc &Desc)
unsigned getExpcntBitMask(const IsaVersion &Version)
bool isInlineValue(unsigned Reg)
bool isGFX10Plus(const MCSubtargetInfo &STI)
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:202
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:209
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:222
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:219
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:224
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:210
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:206
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:201
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:208
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:207
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:218
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:216
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:211
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:205
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:225
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:236
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:237
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:212
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:204
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:221
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:217
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:223
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:213
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:238
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:220
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:203
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:228
bool isGFX9Plus(const MCSubtargetInfo &STI)
MCPhysReg getVGPRWithMSBs(MCPhysReg Reg, unsigned MSBs, const MCRegisterInfo &MRI)
If Reg is a low VGPR return a corresponding high VGPR with MSBs set.
bool isCvt_F32_Fp8_Bf8_e64(unsigned Opc)
MCRegister mc2PseudoReg(MCRegister Reg)
Convert hardware register Reg to a pseudo register.
bool isCI(const MCSubtargetInfo &STI)
bool getVOP2IsSingle(unsigned Opc)
bool isPermlane16(unsigned Opc)
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:307
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:293
Op::Description Desc
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:159
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:164
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
To bit_cast(const From &from) noexcept
Definition bit.h:90
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition MathExtras.h:559
@ Default
The result values are uniform if and only if all operands are uniform.
Definition Uniformity.h:20
#define N
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
Instruction set architecture version.