36 const MCRegisterInfo &MRI;
37 const MCInstrInfo &MCII;
40 AMDGPUMCCodeEmitter(
const MCInstrInfo &MCII,
const MCRegisterInfo &MRI)
41 : MRI(MRI), MCII(MCII) {}
44 void encodeInstruction(
const MCInst &
MI, SmallVectorImpl<char> &CB,
45 SmallVectorImpl<MCFixup> &Fixups,
46 const MCSubtargetInfo &STI)
const override;
48 void getMachineOpValue(
const MCInst &
MI,
const MCOperand &MO, APInt &
Op,
49 SmallVectorImpl<MCFixup> &Fixups,
50 const MCSubtargetInfo &STI)
const;
52 void getMachineOpValueT16(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
53 SmallVectorImpl<MCFixup> &Fixups,
54 const MCSubtargetInfo &STI)
const;
56 void getMachineOpValueT16Lo128(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
57 SmallVectorImpl<MCFixup> &Fixups,
58 const MCSubtargetInfo &STI)
const;
62 void getSOPPBrEncoding(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
63 SmallVectorImpl<MCFixup> &Fixups,
64 const MCSubtargetInfo &STI)
const;
66 void getSMEMOffsetEncoding(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
67 SmallVectorImpl<MCFixup> &Fixups,
68 const MCSubtargetInfo &STI)
const;
70 void getSDWASrcEncoding(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
71 SmallVectorImpl<MCFixup> &Fixups,
72 const MCSubtargetInfo &STI)
const;
74 void getSDWAVopcDstEncoding(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
75 SmallVectorImpl<MCFixup> &Fixups,
76 const MCSubtargetInfo &STI)
const;
78 void getAVOperandEncoding(
const MCInst &
MI,
unsigned OpNo, APInt &
Op,
79 SmallVectorImpl<MCFixup> &Fixups,
80 const MCSubtargetInfo &STI)
const;
83 uint64_t getImplicitOpSelHiEncoding(
int Opcode)
const;
84 void getMachineOpValueCommon(
const MCInst &
MI,
const MCOperand &MO,
85 unsigned OpNo, APInt &
Op,
86 SmallVectorImpl<MCFixup> &Fixups,
87 const MCSubtargetInfo &STI)
const;
90 std::optional<uint64_t>
91 getLitEncoding(
const MCInstrDesc &
Desc,
const MCOperand &MO,
unsigned OpNo,
92 const MCSubtargetInfo &STI,
93 bool HasMandatoryLiteral =
false)
const;
95 void getBinaryCodeForInstr(
const MCInst &
MI, SmallVectorImpl<MCFixup> &Fixups,
96 APInt &Inst, APInt &Scratch,
97 const MCSubtargetInfo &STI)
const;
99 template <
bool HasSrc0,
bool HasSrc1,
bool HasSrc2>
100 APInt postEncodeVOP3(
const MCInst &
MI, APInt EncodedValue,
101 const MCSubtargetInfo &STI)
const;
103 APInt postEncodeVOPCX(
const MCInst &
MI, APInt EncodedValue,
104 const MCSubtargetInfo &STI)
const;
106 APInt postEncodeLdScale(
const MCInst &
MI, APInt EncodedValue,
107 const MCSubtargetInfo &STI)
const;
114 return new AMDGPUMCCodeEmitter(MCII, *Ctx.getRegisterInfo());
124template <
typename IntTy>
126 if (Imm >= 0 && Imm <= 64)
129 if (Imm >= -16 && Imm <= -1)
130 return 192 + std::abs(Imm);
165 STI.
hasFeature(AMDGPU::FeatureInv2PiInlineImm))
178 case 0x3F00:
return 240;
179 case 0xBF00:
return 241;
180 case 0x3F80:
return 242;
181 case 0xBF80:
return 243;
182 case 0x4000:
return 244;
183 case 0xC000:
return 245;
184 case 0x4080:
return 246;
185 case 0xC080:
return 247;
186 case 0x3E22:
return 248;
221 if (Val == 0x3e22f983 &&
222 STI.
hasFeature(AMDGPU::FeatureInv2PiInlineImm))
262 if (Val == 0x3fc45f306dc9c882 &&
263 STI.
hasFeature(AMDGPU::FeatureInv2PiInlineImm))
268 bool CanUse64BitLiterals =
269 STI.
hasFeature(AMDGPU::Feature64BitLiterals) &&
272 return CanUse64BitLiterals &&
Lo_32(Val) ? 254 : 255;
279std::optional<uint64_t> AMDGPUMCCodeEmitter::getLitEncoding(
282 const MCOperandInfo &OpInfo =
Desc.operands()[OpNo];
285 if (!MO.
getExpr()->evaluateAsAbsolute(Imm) ||
291 if (STI.
hasFeature(AMDGPU::Feature64BitLiterals) &&
327 return (HasMandatoryLiteral && Enc == 255) ? 254 : Enc;
381uint64_t AMDGPUMCCodeEmitter::getImplicitOpSelHiEncoding(
int Opcode)
const {
382 using namespace AMDGPU::VOP3PEncoding;
395void AMDGPUMCCodeEmitter::encodeInstruction(
const MCInst &
MI,
396 SmallVectorImpl<char> &CB,
397 SmallVectorImpl<MCFixup> &Fixups,
398 const MCSubtargetInfo &STI)
const {
399 int Opcode =
MI.getOpcode();
400 APInt Encoding, Scratch;
401 getBinaryCodeForInstr(
MI, Fixups, Encoding, Scratch, STI);
402 const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
403 unsigned bytes =
Desc.getSize();
408 Opcode == AMDGPU::V_ACCVGPR_READ_B32_vi ||
409 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_vi) &&
416 Encoding |= getImplicitOpSelHiEncoding(Opcode);
419 for (
unsigned i = 0; i < bytes; i++) {
425 int vaddr0 = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
426 AMDGPU::OpName::vaddr0);
427 int srsrc = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
428 AMDGPU::OpName::srsrc);
429 assert(vaddr0 >= 0 && srsrc > vaddr0);
430 unsigned NumExtraAddrs = srsrc - vaddr0 - 1;
431 unsigned NumPadding = (-NumExtraAddrs) & 3;
433 for (
unsigned i = 0; i < NumExtraAddrs; ++i) {
434 getMachineOpValue(
MI,
MI.getOperand(vaddr0 + 1 + i), Encoding, Fixups,
441 if ((bytes > 8 && STI.
hasFeature(AMDGPU::FeatureVOP3Literal)) ||
442 (bytes > 4 && !STI.
hasFeature(AMDGPU::FeatureVOP3Literal)))
450 for (
unsigned i = 0, e =
Desc.getNumOperands(); i < e; ++i) {
457 const MCOperand &
Op =
MI.getOperand(i);
458 auto Enc = getLitEncoding(
Desc,
Op, i, STI);
459 if (!Enc || (*Enc != 255 && *Enc != 254))
468 else if (
Op.isExpr()) {
493void AMDGPUMCCodeEmitter::getSOPPBrEncoding(
const MCInst &
MI,
unsigned OpNo,
495 SmallVectorImpl<MCFixup> &Fixups,
496 const MCSubtargetInfo &STI)
const {
497 const MCOperand &MO =
MI.getOperand(OpNo);
500 const MCExpr *Expr = MO.
getExpr();
504 getMachineOpValue(
MI, MO,
Op, Fixups, STI);
508void AMDGPUMCCodeEmitter::getSMEMOffsetEncoding(
509 const MCInst &
MI,
unsigned OpNo, APInt &
Op,
510 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
511 auto Offset =
MI.getOperand(OpNo).getImm();
517void AMDGPUMCCodeEmitter::getSDWASrcEncoding(
const MCInst &
MI,
unsigned OpNo,
519 SmallVectorImpl<MCFixup> &Fixups,
520 const MCSubtargetInfo &STI)
const {
521 using namespace AMDGPU::SDWA;
525 const MCOperand &MO =
MI.getOperand(OpNo);
529 RegEnc |=
MRI.getEncodingValue(
Reg);
530 RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
532 RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
537 const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
538 auto Enc = getLitEncoding(
Desc, MO, OpNo, STI);
539 if (Enc && *Enc != 255) {
540 Op = *Enc | SDWA9EncValues::SRC_SGPR_MASK;
548void AMDGPUMCCodeEmitter::getSDWAVopcDstEncoding(
549 const MCInst &
MI,
unsigned OpNo, APInt &
Op,
550 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
551 using namespace AMDGPU::SDWA;
555 const MCOperand &MO =
MI.getOperand(OpNo);
558 if (
Reg != AMDGPU::VCC &&
Reg != AMDGPU::VCC_LO) {
559 RegEnc |=
MRI.getEncodingValue(
Reg);
560 RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
561 RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
566void AMDGPUMCCodeEmitter::getAVOperandEncoding(
567 const MCInst &
MI,
unsigned OpNo, APInt &
Op,
568 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
569 MCRegister
Reg =
MI.getOperand(OpNo).getReg();
570 unsigned Enc =
MRI.getEncodingValue(
Reg);
580 Op = Idx | (IsVGPROrAGPR << 8) | (IsAGPR << 9);
607void AMDGPUMCCodeEmitter::getMachineOpValue(
const MCInst &
MI,
608 const MCOperand &MO, APInt &
Op,
609 SmallVectorImpl<MCFixup> &Fixups,
610 const MCSubtargetInfo &STI)
const {
612 unsigned Enc =
MRI.getEncodingValue(MO.
getReg());
616 Op = Idx | (IsVGPROrAGPR << 8);
619 unsigned OpNo = &MO -
MI.begin();
620 getMachineOpValueCommon(
MI, MO, OpNo,
Op, Fixups, STI);
623void AMDGPUMCCodeEmitter::getMachineOpValueT16(
624 const MCInst &
MI,
unsigned OpNo, APInt &
Op,
625 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
626 const MCOperand &MO =
MI.getOperand(OpNo);
628 unsigned Enc =
MRI.getEncodingValue(MO.
getReg());
631 Op = Idx | (IsVGPR << 8);
634 getMachineOpValueCommon(
MI, MO, OpNo,
Op, Fixups, STI);
641 if ((
int)OpNo == AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
642 AMDGPU::OpName::src0_modifiers)) {
643 SrcMOIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
645 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdst);
646 if (VDstMOIdx != -1) {
647 auto DstReg =
MI.getOperand(VDstMOIdx).getReg();
651 }
else if ((
int)OpNo == AMDGPU::getNamedOperandIdx(
652 MI.getOpcode(), AMDGPU::OpName::src1_modifiers))
653 SrcMOIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
654 else if ((
int)OpNo == AMDGPU::getNamedOperandIdx(
655 MI.getOpcode(), AMDGPU::OpName::src2_modifiers))
656 SrcMOIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src2);
660 const MCOperand &SrcMO =
MI.getOperand(SrcMOIdx);
663 auto SrcReg = SrcMO.
getReg();
670void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
671 const MCInst &
MI,
unsigned OpNo, APInt &
Op,
672 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
673 const MCOperand &MO =
MI.getOperand(OpNo);
675 uint16_t Encoding =
MRI.getEncodingValue(MO.
getReg());
680 Op = (IsVGPR ? 0x100 : 0) | (IsHi ? 0x80 : 0) | RegIdx;
683 getMachineOpValueCommon(
MI, MO, OpNo,
Op, Fixups, STI);
686void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
687 const MCInst &
MI,
const MCOperand &MO,
unsigned OpNo, APInt &
Op,
688 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
689 bool isLikeImm =
false;
695 }
else if (MO.
isExpr() && MO.
getExpr()->evaluateAsAbsolute(Val)) {
709 const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
717 const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
719 bool HasMandatoryLiteral =
721 if (
auto Enc = getLitEncoding(
Desc, MO, OpNo, STI, HasMandatoryLiteral)) {
737template <
bool HasSrc0,
bool HasSrc1,
bool HasSrc2>
738APInt AMDGPUMCCodeEmitter::postEncodeVOP3(
const MCInst &
MI, APInt EncodedValue,
739 const MCSubtargetInfo &STI)
const {
744 constexpr uint64_t InlineImmediate0 = 0x80;
746 EncodedValue |= InlineImmediate0 << 32;
748 EncodedValue |= InlineImmediate0 << 41;
750 EncodedValue |= InlineImmediate0 << 50;
754APInt AMDGPUMCCodeEmitter::postEncodeVOPCX(
const MCInst &
MI, APInt EncodedValue,
755 const MCSubtargetInfo &STI)
const {
762 [[maybe_unused]]
const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
764 Desc.hasImplicitDefOfPhysReg(AMDGPU::EXEC));
765 EncodedValue |=
MRI.getEncodingValue(AMDGPU::EXEC_LO) &
767 return postEncodeVOP3<true, true, false>(
MI, EncodedValue, STI);
770APInt AMDGPUMCCodeEmitter::postEncodeLdScale(
const MCInst &
MI,
772 const MCSubtargetInfo &STI)
const {
775 constexpr uint64_t Vgpr0 = 0x100;
776 EncodedValue |= Vgpr0 << 50;
780#include "AMDGPUGenMCCodeEmitter.inc"
unsigned const MachineRegisterInfo * MRI
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t getLit64Encoding(const MCInstrDesc &Desc, uint64_t Val, const MCSubtargetInfo &STI, bool IsFP)
static uint32_t getLit16IntEncoding(uint32_t Val, const MCSubtargetInfo &STI)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
static uint32_t getLitBF16Encoding(uint16_t Val)
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...
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
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.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
MCCodeEmitter - Generic instruction encoding interface.
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
@ Unary
Unary expressions.
@ Constant
Constant expressions.
@ SymbolRef
References to labels and assigned expressions.
@ Target
Target specific expression.
@ Specifier
Expression with a relocation specifier.
@ Binary
Binary expressions.
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
uint8_t OperandType
Information about the type of the operand.
Instances of this class represent operands of the MCInst class.
MCRegister getReg() const
Returns the register number.
const MCExpr * getExpr() const
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...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
static AMDGPUMCExpr::Specifier getSpecifier(const MCSymbolRefExpr *SRE)
LLVM_READONLY bool isLitExpr(const MCExpr *Expr)
@ fixup_si_sopp_br
16-bit PC relative fixup for SOPP branch instructions.
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
LLVM_READONLY int64_t getLitValue(const MCExpr *Expr)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
bool isGFX10Plus(const MCSubtargetInfo &STI)
int64_t encode32BitLiteral(int64_t Imm, OperandType Type, bool IsLit)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
std::optional< unsigned > getPKFMACF16InlineEncoding(uint32_t Literal, bool IsGFX11Plus)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
bool isVI(const MCSubtargetInfo &STI)
MCRegister mc2PseudoReg(MCRegister Reg)
Convert hardware register Reg to a pseudo register.
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
@ C
The default llvm calling convention, compatible with C.
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
MCCodeEmitter * createAMDGPUMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)