Thanks to visit codestin.com
Credit goes to llvm.org

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