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