LLVM 19.0.0git
AMDGPUMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- AMDGPUMCCodeEmitter.cpp - AMDGPU Code Emitter ---------------------===//
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//===----------------------------------------------------------------------===//
8//
9/// \file
10/// The AMDGPU code emitter produces machine code that can be executed
11/// directly on the GPU device.
12//
13//===----------------------------------------------------------------------===//
14
17#include "SIDefines.h"
19#include "llvm/ADT/APInt.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInstrInfo.h"
29#include <optional>
30
31using namespace llvm;
32
33namespace {
34
35class AMDGPUMCCodeEmitter : public MCCodeEmitter {
36 const MCRegisterInfo &MRI;
37 const MCInstrInfo &MCII;
38
39public:
40 AMDGPUMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI)
41 : MRI(MRI), MCII(MCII) {}
42
43 /// Encode the instruction and write it to the OS.
46 const MCSubtargetInfo &STI) const override;
47
48 void getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &Op,
50 const MCSubtargetInfo &STI) const;
51
52 void getMachineOpValueT16(const MCInst &MI, unsigned OpNo, APInt &Op,
54 const MCSubtargetInfo &STI) const;
55
56 void getMachineOpValueT16Lo128(const MCInst &MI, unsigned OpNo, APInt &Op,
58 const MCSubtargetInfo &STI) const;
59
60 /// Use a fixup to encode the simm16 field for SOPP branch
61 /// instructions.
62 void getSOPPBrEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
64 const MCSubtargetInfo &STI) const;
65
66 void getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
68 const MCSubtargetInfo &STI) const;
69
70 void getSDWASrcEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
72 const MCSubtargetInfo &STI) const;
73
74 void getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
76 const MCSubtargetInfo &STI) const;
77
78 void getAVOperandEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
80 const MCSubtargetInfo &STI) const;
81
82private:
83 uint64_t getImplicitOpSelHiEncoding(int Opcode) const;
84 void getMachineOpValueCommon(const MCInst &MI, const MCOperand &MO,
85 unsigned OpNo, APInt &Op,
87 const MCSubtargetInfo &STI) const;
88
89 /// Encode an fp or int literal.
90 std::optional<uint32_t> getLitEncoding(const MCOperand &MO,
91 const MCOperandInfo &OpInfo,
92 const MCSubtargetInfo &STI) const;
93
94 void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
95 APInt &Inst, APInt &Scratch,
96 const MCSubtargetInfo &STI) const;
97};
98
99} // end anonymous namespace
100
102 MCContext &Ctx) {
103 return new AMDGPUMCCodeEmitter(MCII, *Ctx.getRegisterInfo());
104}
105
106// Returns the encoding value to use if the given integer is an integer inline
107// immediate value, or 0 if it is not.
108template <typename IntTy>
110 if (Imm >= 0 && Imm <= 64)
111 return 128 + Imm;
112
113 if (Imm >= -16 && Imm <= -1)
114 return 192 + std::abs(Imm);
115
116 return 0;
117}
118
120 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
121 return IntImm == 0 ? 255 : IntImm;
122}
123
125 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
126 if (IntImm != 0)
127 return IntImm;
128
129 if (Val == 0x3800) // 0.5
130 return 240;
131
132 if (Val == 0xB800) // -0.5
133 return 241;
134
135 if (Val == 0x3C00) // 1.0
136 return 242;
137
138 if (Val == 0xBC00) // -1.0
139 return 243;
140
141 if (Val == 0x4000) // 2.0
142 return 244;
143
144 if (Val == 0xC000) // -2.0
145 return 245;
146
147 if (Val == 0x4400) // 4.0
148 return 246;
149
150 if (Val == 0xC400) // -4.0
151 return 247;
152
153 if (Val == 0x3118 && // 1.0 / (2.0 * pi)
154 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
155 return 248;
156
157 return 255;
158}
159
161 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
162 if (IntImm != 0)
163 return IntImm;
164
165 // clang-format off
166 switch (Val) {
167 case 0x3F00: return 240; // 0.5
168 case 0xBF00: return 241; // -0.5
169 case 0x3F80: return 242; // 1.0
170 case 0xBF80: return 243; // -1.0
171 case 0x4000: return 244; // 2.0
172 case 0xC000: return 245; // -2.0
173 case 0x4080: return 246; // 4.0
174 case 0xC080: return 247; // -4.0
175 case 0x3E22: return 248; // 1.0 / (2.0 * pi)
176 default: return 255;
177 }
178 // clang-format on
179}
180
182 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
183 if (IntImm != 0)
184 return IntImm;
185
186 if (Val == llvm::bit_cast<uint32_t>(0.5f))
187 return 240;
188
189 if (Val == llvm::bit_cast<uint32_t>(-0.5f))
190 return 241;
191
192 if (Val == llvm::bit_cast<uint32_t>(1.0f))
193 return 242;
194
195 if (Val == llvm::bit_cast<uint32_t>(-1.0f))
196 return 243;
197
198 if (Val == llvm::bit_cast<uint32_t>(2.0f))
199 return 244;
200
201 if (Val == llvm::bit_cast<uint32_t>(-2.0f))
202 return 245;
203
204 if (Val == llvm::bit_cast<uint32_t>(4.0f))
205 return 246;
206
207 if (Val == llvm::bit_cast<uint32_t>(-4.0f))
208 return 247;
209
210 if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
211 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
212 return 248;
213
214 return 255;
215}
216
218 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
219 if (IntImm != 0)
220 return IntImm;
221
222 if (Val == llvm::bit_cast<uint64_t>(0.5))
223 return 240;
224
225 if (Val == llvm::bit_cast<uint64_t>(-0.5))
226 return 241;
227
228 if (Val == llvm::bit_cast<uint64_t>(1.0))
229 return 242;
230
231 if (Val == llvm::bit_cast<uint64_t>(-1.0))
232 return 243;
233
234 if (Val == llvm::bit_cast<uint64_t>(2.0))
235 return 244;
236
237 if (Val == llvm::bit_cast<uint64_t>(-2.0))
238 return 245;
239
240 if (Val == llvm::bit_cast<uint64_t>(4.0))
241 return 246;
242
243 if (Val == llvm::bit_cast<uint64_t>(-4.0))
244 return 247;
245
246 if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
247 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
248 return 248;
249
250 return 255;
251}
252
253std::optional<uint32_t>
254AMDGPUMCCodeEmitter::getLitEncoding(const MCOperand &MO,
255 const MCOperandInfo &OpInfo,
256 const MCSubtargetInfo &STI) const {
257 int64_t Imm;
258 if (MO.isExpr()) {
259 const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
260 if (!C)
261 return 255;
262
263 Imm = C->getValue();
264 } else {
265
266 assert(!MO.isDFPImm());
267
268 if (!MO.isImm())
269 return {};
270
271 Imm = MO.getImm();
272 }
273
274 switch (OpInfo.OperandType) {
287 return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
288
294 return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
295
299 return getLit16IntEncoding(static_cast<uint16_t>(Imm), STI);
300
305 // FIXME Is this correct? What do inline immediates do on SI for f16 src
306 // which does not have f16 support?
307 return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
308
313 // We don't actually need to check Inv2Pi here because BF16 instructions can
314 // only be emitted for targets that already support the feature.
315 return getLitBF16Encoding(static_cast<uint16_t>(Imm));
316
320 return AMDGPU::getInlineEncodingV2I16(static_cast<uint32_t>(Imm))
321 .value_or(255);
322
326 return AMDGPU::getInlineEncodingV2F16(static_cast<uint32_t>(Imm))
327 .value_or(255);
328
332 return AMDGPU::getInlineEncodingV2BF16(static_cast<uint32_t>(Imm))
333 .value_or(255);
334
337 return MO.getImm();
338 default:
339 llvm_unreachable("invalid operand size");
340 }
341}
342
343uint64_t AMDGPUMCCodeEmitter::getImplicitOpSelHiEncoding(int Opcode) const {
344 using namespace AMDGPU::VOP3PEncoding;
345 using namespace AMDGPU::OpName;
346
347 if (AMDGPU::hasNamedOperand(Opcode, op_sel_hi)) {
348 if (AMDGPU::hasNamedOperand(Opcode, src2))
349 return 0;
350 if (AMDGPU::hasNamedOperand(Opcode, src1))
351 return OP_SEL_HI_2;
352 if (AMDGPU::hasNamedOperand(Opcode, src0))
353 return OP_SEL_HI_1 | OP_SEL_HI_2;
354 }
356}
357
358static bool isVCMPX64(const MCInstrDesc &Desc) {
359 return (Desc.TSFlags & SIInstrFlags::VOP3) &&
360 Desc.hasImplicitDefOfPhysReg(AMDGPU::EXEC);
361}
362
363void AMDGPUMCCodeEmitter::encodeInstruction(const MCInst &MI,
366 const MCSubtargetInfo &STI) const {
367 int Opcode = MI.getOpcode();
368 APInt Encoding, Scratch;
369 getBinaryCodeForInstr(MI, Fixups, Encoding, Scratch, STI);
370 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
371 unsigned bytes = Desc.getSize();
372
373 // Set unused op_sel_hi bits to 1 for VOP3P and MAI instructions.
374 // Note that accvgpr_read/write are MAI, have src0, but do not use op_sel.
375 if ((Desc.TSFlags & SIInstrFlags::VOP3P) ||
376 Opcode == AMDGPU::V_ACCVGPR_READ_B32_vi ||
377 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_vi) {
378 Encoding |= getImplicitOpSelHiEncoding(Opcode);
379 }
380
381 // GFX10+ v_cmpx opcodes promoted to VOP3 have implied dst=EXEC.
382 // Documentation requires dst to be encoded as EXEC (0x7E),
383 // but it looks like the actual value encoded for dst operand
384 // is ignored by HW. It was decided to define dst as "do not care"
385 // in td files to allow disassembler accept any dst value.
386 // However, dst is encoded as EXEC for compatibility with SP3.
387 if (AMDGPU::isGFX10Plus(STI) && isVCMPX64(Desc)) {
388 assert((Encoding & 0xFF) == 0);
389 Encoding |= MRI.getEncodingValue(AMDGPU::EXEC_LO) &
391 }
392
393 for (unsigned i = 0; i < bytes; i++) {
394 CB.push_back((uint8_t)Encoding.extractBitsAsZExtValue(8, 8 * i));
395 }
396
397 // NSA encoding.
398 if (AMDGPU::isGFX10Plus(STI) && Desc.TSFlags & SIInstrFlags::MIMG) {
399 int vaddr0 = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
400 AMDGPU::OpName::vaddr0);
401 int srsrc = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
402 AMDGPU::OpName::srsrc);
403 assert(vaddr0 >= 0 && srsrc > vaddr0);
404 unsigned NumExtraAddrs = srsrc - vaddr0 - 1;
405 unsigned NumPadding = (-NumExtraAddrs) & 3;
406
407 for (unsigned i = 0; i < NumExtraAddrs; ++i) {
408 getMachineOpValue(MI, MI.getOperand(vaddr0 + 1 + i), Encoding, Fixups,
409 STI);
410 CB.push_back((uint8_t)Encoding.getLimitedValue());
411 }
412 CB.append(NumPadding, 0);
413 }
414
415 if ((bytes > 8 && STI.hasFeature(AMDGPU::FeatureVOP3Literal)) ||
416 (bytes > 4 && !STI.hasFeature(AMDGPU::FeatureVOP3Literal)))
417 return;
418
419 // Do not print literals from SISrc Operands for insts with mandatory literals
420 if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm))
421 return;
422
423 // Check for additional literals
424 for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
425
426 // Check if this operand should be encoded as [SV]Src
428 continue;
429
430 // Is this operand a literal immediate?
431 const MCOperand &Op = MI.getOperand(i);
432 auto Enc = getLitEncoding(Op, Desc.operands()[i], STI);
433 if (!Enc || *Enc != 255)
434 continue;
435
436 // Yes! Encode it
437 int64_t Imm = 0;
438
439 if (Op.isImm())
440 Imm = Op.getImm();
441 else if (Op.isExpr()) {
442 if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
443 Imm = C->getValue();
444 } else // Exprs will be replaced with a fixup value.
445 llvm_unreachable("Must be immediate or expr");
446
447 if (Desc.operands()[i].OperandType == AMDGPU::OPERAND_REG_IMM_FP64)
448 Imm = Hi_32(Imm);
449
450 support::endian::write<uint32_t>(CB, Imm, llvm::endianness::little);
451
452 // Only one literal value allowed
453 break;
454 }
455}
456
457void AMDGPUMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
458 APInt &Op,
460 const MCSubtargetInfo &STI) const {
461 const MCOperand &MO = MI.getOperand(OpNo);
462
463 if (MO.isExpr()) {
464 const MCExpr *Expr = MO.getExpr();
466 Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
467 Op = APInt::getZero(96);
468 } else {
469 getMachineOpValue(MI, MO, Op, Fixups, STI);
470 }
471}
472
473void AMDGPUMCCodeEmitter::getSMEMOffsetEncoding(
474 const MCInst &MI, unsigned OpNo, APInt &Op,
475 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
476 auto Offset = MI.getOperand(OpNo).getImm();
477 // VI only supports 20-bit unsigned offsets.
478 assert(!AMDGPU::isVI(STI) || isUInt<20>(Offset));
479 Op = Offset;
480}
481
482void AMDGPUMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
483 APInt &Op,
485 const MCSubtargetInfo &STI) const {
486 using namespace AMDGPU::SDWA;
487
488 uint64_t RegEnc = 0;
489
490 const MCOperand &MO = MI.getOperand(OpNo);
491
492 if (MO.isReg()) {
493 unsigned Reg = MO.getReg();
494 RegEnc |= MRI.getEncodingValue(Reg);
495 RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
497 RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
498 }
499 Op = RegEnc;
500 return;
501 } else {
502 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
503 auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI);
504 if (Enc && *Enc != 255) {
505 Op = *Enc | SDWA9EncValues::SRC_SGPR_MASK;
506 return;
507 }
508 }
509
510 llvm_unreachable("Unsupported operand kind");
511}
512
513void AMDGPUMCCodeEmitter::getSDWAVopcDstEncoding(
514 const MCInst &MI, unsigned OpNo, APInt &Op,
515 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
516 using namespace AMDGPU::SDWA;
517
518 uint64_t RegEnc = 0;
519
520 const MCOperand &MO = MI.getOperand(OpNo);
521
522 unsigned Reg = MO.getReg();
523 if (Reg != AMDGPU::VCC && Reg != AMDGPU::VCC_LO) {
524 RegEnc |= MRI.getEncodingValue(Reg);
525 RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
526 RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
527 }
528 Op = RegEnc;
529}
530
531void AMDGPUMCCodeEmitter::getAVOperandEncoding(
532 const MCInst &MI, unsigned OpNo, APInt &Op,
533 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
534 unsigned Reg = MI.getOperand(OpNo).getReg();
535 unsigned Enc = MRI.getEncodingValue(Reg);
536 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
537 bool IsVGPROrAGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
538
539 // VGPR and AGPR have the same encoding, but SrcA and SrcB operands of mfma
540 // instructions use acc[0:1] modifier bits to distinguish. These bits are
541 // encoded as a virtual 9th bit of the register for these operands.
542 bool IsAGPR = false;
543 if (MRI.getRegClass(AMDGPU::AGPR_32RegClassID).contains(Reg) ||
544 MRI.getRegClass(AMDGPU::AReg_64RegClassID).contains(Reg) ||
545 MRI.getRegClass(AMDGPU::AReg_96RegClassID).contains(Reg) ||
546 MRI.getRegClass(AMDGPU::AReg_128RegClassID).contains(Reg) ||
547 MRI.getRegClass(AMDGPU::AReg_160RegClassID).contains(Reg) ||
548 MRI.getRegClass(AMDGPU::AReg_192RegClassID).contains(Reg) ||
549 MRI.getRegClass(AMDGPU::AReg_224RegClassID).contains(Reg) ||
550 MRI.getRegClass(AMDGPU::AReg_256RegClassID).contains(Reg) ||
551 MRI.getRegClass(AMDGPU::AReg_288RegClassID).contains(Reg) ||
552 MRI.getRegClass(AMDGPU::AReg_320RegClassID).contains(Reg) ||
553 MRI.getRegClass(AMDGPU::AReg_352RegClassID).contains(Reg) ||
554 MRI.getRegClass(AMDGPU::AReg_384RegClassID).contains(Reg) ||
555 MRI.getRegClass(AMDGPU::AReg_512RegClassID).contains(Reg) ||
556 MRI.getRegClass(AMDGPU::AGPR_LO16RegClassID).contains(Reg))
557 IsAGPR = true;
558
559 Op = Idx | (IsVGPROrAGPR << 8) | (IsAGPR << 9);
560}
561
562static bool needsPCRel(const MCExpr *Expr) {
563 switch (Expr->getKind()) {
564 case MCExpr::SymbolRef: {
565 auto *SE = cast<MCSymbolRefExpr>(Expr);
566 MCSymbolRefExpr::VariantKind Kind = SE->getKind();
569 }
570 case MCExpr::Binary: {
571 auto *BE = cast<MCBinaryExpr>(Expr);
572 if (BE->getOpcode() == MCBinaryExpr::Sub)
573 return false;
574 return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
575 }
576 case MCExpr::Unary:
577 return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
578 case MCExpr::Target:
579 case MCExpr::Constant:
580 return false;
581 }
582 llvm_unreachable("invalid kind");
583}
584
585void AMDGPUMCCodeEmitter::getMachineOpValue(const MCInst &MI,
586 const MCOperand &MO, APInt &Op,
588 const MCSubtargetInfo &STI) const {
589 if (MO.isReg()){
590 unsigned Enc = MRI.getEncodingValue(MO.getReg());
591 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
592 bool IsVGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
593 Op = Idx | (IsVGPR << 8);
594 return;
595 }
596 unsigned OpNo = &MO - MI.begin();
597 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
598}
599
600void AMDGPUMCCodeEmitter::getMachineOpValueT16(
601 const MCInst &MI, unsigned OpNo, APInt &Op,
602 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
603 const MCOperand &MO = MI.getOperand(OpNo);
604 if (MO.isReg()) {
605 unsigned Enc = MRI.getEncodingValue(MO.getReg());
606 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
607 bool IsVGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
608 Op = Idx | (IsVGPR << 8);
609 return;
610 }
611 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
612 // VGPRs include the suffix/op_sel bit in the register encoding, but
613 // immediates and SGPRs include it in src_modifiers. Therefore, copy the
614 // op_sel bit from the src operands into src_modifier operands if Op is
615 // src_modifiers and the corresponding src is a VGPR
616 int SrcMOIdx = -1;
617 assert(OpNo < INT_MAX);
618 if ((int)OpNo == AMDGPU::getNamedOperandIdx(MI.getOpcode(),
619 AMDGPU::OpName::src0_modifiers)) {
620 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
621 int VDstMOIdx =
622 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst);
623 if (VDstMOIdx != -1) {
624 auto DstReg = MI.getOperand(VDstMOIdx).getReg();
625 if (AMDGPU::isHi(DstReg, MRI))
627 }
628 } else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
629 MI.getOpcode(), AMDGPU::OpName::src1_modifiers))
630 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
631 else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
632 MI.getOpcode(), AMDGPU::OpName::src2_modifiers))
633 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src2);
634 if (SrcMOIdx == -1)
635 return;
636
637 const MCOperand &SrcMO = MI.getOperand(SrcMOIdx);
638 if (!SrcMO.isReg())
639 return;
640 auto SrcReg = SrcMO.getReg();
641 if (AMDGPU::isSGPR(SrcReg, &MRI))
642 return;
643 if (AMDGPU::isHi(SrcReg, MRI))
645}
646
647void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
648 const MCInst &MI, unsigned OpNo, APInt &Op,
649 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
650 const MCOperand &MO = MI.getOperand(OpNo);
651 if (MO.isReg()) {
652 uint16_t Encoding = MRI.getEncodingValue(MO.getReg());
653 unsigned RegIdx = Encoding & AMDGPU::HWEncoding::REG_IDX_MASK;
654 bool IsHi = Encoding & AMDGPU::HWEncoding::IS_HI;
655 bool IsVGPR = Encoding & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
656 assert((!IsVGPR || isUInt<7>(RegIdx)) && "VGPR0-VGPR127 expected!");
657 Op = (IsVGPR ? 0x100 : 0) | (IsHi ? 0x80 : 0) | RegIdx;
658 return;
659 }
660 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
661}
662
663void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
664 const MCInst &MI, const MCOperand &MO, unsigned OpNo, APInt &Op,
665 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
666
667 if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
668 // FIXME: If this is expression is PCRel or not should not depend on what
669 // the expression looks like. Given that this is just a general expression,
670 // it should probably be FK_Data_4 and whatever is producing
671 //
672 // s_add_u32 s2, s2, (extern_const_addrspace+16
673 //
674 // And expecting a PCRel should instead produce
675 //
676 // .Ltmp1:
677 // s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
679 if (needsPCRel(MO.getExpr()))
681 else
682 Kind = FK_Data_4;
683
684 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
685 uint32_t Offset = Desc.getSize();
686 assert(Offset == 4 || Offset == 8);
687
688 Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), Kind, MI.getLoc()));
689 }
690
691 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
692 if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
693 if (auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI)) {
694 Op = *Enc;
695 return;
696 }
697 } else if (MO.isImm()) {
698 Op = MO.getImm();
699 return;
700 }
701
702 llvm_unreachable("Encoding of this operand type is not supported yet.");
703}
704
705#include "AMDGPUGenMCCodeEmitter.inc"
unsigned const MachineRegisterInfo * MRI
static uint32_t getLit16IntEncoding(uint16_t Val, const MCSubtargetInfo &STI)
static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI)
static uint32_t getLitBF16Encoding(uint16_t Val)
static bool isVCMPX64(const MCInstrDesc &Desc)
static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI)
static uint32_t getIntInlineImmEncoding(IntTy Imm)
static bool needsPCRel(const MCExpr *Expr)
static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI)
Provides AMDGPU specific target descriptions.
This file implements a class to represent arbitrary precision integral constant values and operations...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
Definition: APInt.h:76
uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
Definition: APInt.cpp:489
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition: APInt.h:453
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:178
This class represents an Operation in the Expression.
@ Sub
Subtraction.
Definition: MCExpr.h:515
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
Context object for machine code objects.
Definition: MCContext.h:76
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:448
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
@ Unary
Unary expressions.
Definition: MCExpr.h:41
@ Constant
Constant expressions.
Definition: MCExpr.h:39
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
@ Target
Target specific expression.
Definition: MCExpr.h:42
@ Binary
Binary expressions.
Definition: MCExpr.h:38
ExprKind getKind() const
Definition: MCExpr.h:81
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:85
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:97
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
bool isDFPImm() const
Definition: MCInst.h:64
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void push_back(const T &Elt)
Definition: SmallVector.h:426
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
unsigned mc2PseudoReg(unsigned Reg)
Convert hardware register Reg to a pseudo register.
@ fixup_si_sopp_br
16-bit PC relative fixup for SOPP branch instructions.
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this an AMDGPU specific source operand? These include registers, inline constants,...
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, uint64_t NamedIdx)
bool isSGPR(unsigned Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
bool isHi(unsigned Reg, const MCRegisterInfo &MRI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
bool isGFX10Plus(const MCSubtargetInfo &STI)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition: SIDefines.h:234
@ OPERAND_REG_IMM_INT64
Definition: SIDefines.h:201
@ OPERAND_REG_IMM_V2FP16
Definition: SIDefines.h:211
@ OPERAND_REG_INLINE_C_V2INT32
Definition: SIDefines.h:227
@ OPERAND_REG_INLINE_C_FP64
Definition: SIDefines.h:223
@ OPERAND_REG_INLINE_C_BF16
Definition: SIDefines.h:220
@ OPERAND_REG_INLINE_C_V2BF16
Definition: SIDefines.h:225
@ OPERAND_REG_IMM_V2INT16
Definition: SIDefines.h:212
@ OPERAND_REG_IMM_BF16
Definition: SIDefines.h:205
@ OPERAND_REG_INLINE_AC_V2FP16
Definition: SIDefines.h:246
@ OPERAND_REG_IMM_INT32
Operands with register or 32-bit immediate.
Definition: SIDefines.h:200
@ OPERAND_REG_IMM_V2BF16
Definition: SIDefines.h:210
@ OPERAND_REG_IMM_BF16_DEFERRED
Definition: SIDefines.h:207
@ OPERAND_REG_IMM_FP16
Definition: SIDefines.h:206
@ OPERAND_REG_INLINE_C_INT64
Definition: SIDefines.h:219
@ OPERAND_REG_INLINE_AC_BF16
Definition: SIDefines.h:240
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition: SIDefines.h:217
@ OPERAND_REG_INLINE_AC_INT16
Operands with an AccVGPR register or inline constant.
Definition: SIDefines.h:238
@ OPERAND_REG_IMM_FP64
Definition: SIDefines.h:204
@ OPERAND_REG_INLINE_C_V2FP16
Definition: SIDefines.h:226
@ OPERAND_REG_INLINE_AC_V2INT16
Definition: SIDefines.h:244
@ OPERAND_REG_INLINE_AC_FP16
Definition: SIDefines.h:241
@ OPERAND_REG_INLINE_AC_INT32
Definition: SIDefines.h:239
@ OPERAND_REG_INLINE_AC_FP32
Definition: SIDefines.h:242
@ OPERAND_REG_INLINE_AC_V2BF16
Definition: SIDefines.h:245
@ OPERAND_REG_IMM_V2INT32
Definition: SIDefines.h:213
@ OPERAND_REG_IMM_FP32
Definition: SIDefines.h:203
@ OPERAND_REG_INLINE_C_FP32
Definition: SIDefines.h:222
@ OPERAND_REG_INLINE_C_INT32
Definition: SIDefines.h:218
@ OPERAND_REG_INLINE_C_V2INT16
Definition: SIDefines.h:224
@ OPERAND_REG_IMM_V2FP32
Definition: SIDefines.h:214
@ OPERAND_REG_INLINE_AC_FP64
Definition: SIDefines.h:243
@ OPERAND_REG_INLINE_C_FP16
Definition: SIDefines.h:221
@ OPERAND_REG_IMM_INT16
Definition: SIDefines.h:202
@ OPERAND_REG_INLINE_C_V2FP32
Definition: SIDefines.h:228
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition: SIDefines.h:231
@ OPERAND_REG_IMM_FP32_DEFERRED
Definition: SIDefines.h:209
@ OPERAND_REG_IMM_FP16_DEFERRED
Definition: SIDefines.h:208
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
bool isVI(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition: MathExtras.h:136
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
@ FK_PCRel_4
A four-byte pc relative fixup.
Definition: MCFixup.h:30
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
MCCodeEmitter * createAMDGPUMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Description of the encoding of one expression Op.