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