Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 51 additions & 34 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -962,11 +962,11 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
if (SIInstrFlags::isSDWA(*MCII, MI))
convertSDWAInst(MI);

if (SIInstrFlags::isMAI(*MCII, MI))
convertMAIInst(MI);
if (SIInstrFlags::isMAI(*MCII, MI) && !convertMAIInst(MI))
return MCDisassembler::Fail;

if (SIInstrFlags::isWMMA(*MCII, MI))
convertWMMAInst(MI);
if (SIInstrFlags::isWMMA(*MCII, MI) && !convertWMMAInst(MI))
return MCDisassembler::Fail;

int VDstIn_Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
AMDGPU::OpName::vdst_in);
Expand Down Expand Up @@ -1065,45 +1065,62 @@ void AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {

/// Adjust the register values used by V_MFMA_F8F6F4_f8_f8 instructions to the
/// appropriate subregister for the used format width.
static void adjustMFMA_F8F6F4OpRegClass(const MCRegisterInfo &MRI,
///
/// \returns false if the operand cannot be narrowed down to \p NumRegs, which
/// means the encoding is malformed.
static bool adjustMFMA_F8F6F4OpRegClass(const MCRegisterInfo &MRI,
MCOperand &MO, uint8_t NumRegs) {
// A malformed encoding can select an operand that is not a register at all.
if (!MO.isReg())
return false;

MCRegister NewReg;
switch (NumRegs) {
case 4:
return MO.setReg(MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3));
NewReg = MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3);
break;
case 6:
return MO.setReg(
MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5));
NewReg = MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5);
break;
case 8:
if (MCRegister NewReg = MRI.getSubReg(
MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7)) {
MO.setReg(NewReg);
}
return;
case 12: {
NewReg = MRI.getSubReg(MO.getReg(),
AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7);
// For mfma f8/f8 is the widest format, so the operand already has the
// requested width and there is no subregister to select.
if (!NewReg)
return true;
break;
case 12:
// There is no 384-bit subreg index defined.
MCRegister BaseReg = MRI.getSubReg(MO.getReg(), AMDGPU::sub0);
MCRegister NewReg = MRI.getMatchingSuperReg(
BaseReg, AMDGPU::sub0, &MRI.getRegClass(AMDGPU::VReg_384RegClassID));
return MO.setReg(NewReg);
}
if (MCRegister BaseReg = MRI.getSubReg(MO.getReg(), AMDGPU::sub0)) {
NewReg = MRI.getMatchingSuperReg(
BaseReg, AMDGPU::sub0, &MRI.getRegClass(AMDGPU::VReg_384RegClassID));
}
break;
case 16:
// No-op in cases where one operand is still f8/bf8.
return;
return true;
default:
llvm_unreachable("Unexpected size for mfma/wmma f8f6f4 operand");
}

if (!NewReg)
return false;

MO.setReg(NewReg);
return true;
}

/// f8f6f4 instructions have different pseudos depending on the used formats. In
/// the disassembler table, we only have the variants with the largest register
/// classes which assume using an fp8/bf8 format for both operands. The actual
/// register class depends on the format in blgp and cbsz operands. Adjust the
/// register classes depending on the used format.
void AMDGPUDisassembler::convertMAIInst(MCInst &MI) const {
bool AMDGPUDisassembler::convertMAIInst(MCInst &MI) const {
int BlgpIdx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::blgp);
if (BlgpIdx == -1)
return;
return true;

int CbszIdx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::cbsz);
Expand All @@ -1115,24 +1132,24 @@ void AMDGPUDisassembler::convertMAIInst(MCInst &MI) const {
AMDGPU::getMFMA_F8F6F4_WithFormatArgs(CBSZ, BLGP, MI.getOpcode());
if (!AdjustedRegClassOpcode ||
AdjustedRegClassOpcode->Opcode == MI.getOpcode())
return;
return true;

MI.setOpcode(AdjustedRegClassOpcode->Opcode);
int Src0Idx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
int Src1Idx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),
AdjustedRegClassOpcode->NumRegsSrcA);
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),
AdjustedRegClassOpcode->NumRegsSrcB);
return adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),
AdjustedRegClassOpcode->NumRegsSrcA) &&
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),
AdjustedRegClassOpcode->NumRegsSrcB);
}

void AMDGPUDisassembler::convertWMMAInst(MCInst &MI) const {
bool AMDGPUDisassembler::convertWMMAInst(MCInst &MI) const {
int FmtAIdx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::matrix_a_fmt);
if (FmtAIdx == -1)
return;
return true;

int FmtBIdx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::matrix_b_fmt);
Expand All @@ -1144,17 +1161,17 @@ void AMDGPUDisassembler::convertWMMAInst(MCInst &MI) const {
AMDGPU::getWMMA_F8F6F4_WithFormatArgs(FmtA, FmtB, MI.getOpcode());
if (!AdjustedRegClassOpcode ||
AdjustedRegClassOpcode->Opcode == MI.getOpcode())
return;
return true;

MI.setOpcode(AdjustedRegClassOpcode->Opcode);
int Src0Idx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
int Src1Idx =
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),
AdjustedRegClassOpcode->NumRegsSrcA);
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),
AdjustedRegClassOpcode->NumRegsSrcB);
return adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),
AdjustedRegClassOpcode->NumRegsSrcA) &&
adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),
AdjustedRegClassOpcode->NumRegsSrcB);
}

struct VOPModifiers {
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ class AMDGPUDisassembler : public MCDisassembler {
void convertVINTERPInst(MCInst &MI) const;
void convertFMAanyK(MCInst &MI) const;
void convertSDWAInst(MCInst &MI) const;
void convertMAIInst(MCInst &MI) const;
void convertWMMAInst(MCInst &MI) const;
bool convertMAIInst(MCInst &MI) const;
bool convertWMMAInst(MCInst &MI) const;
void convertDPP8Inst(MCInst &MI) const;
void convertMIMGInst(MCInst &MI) const;
void convertVOP3DPPInst(MCInst &MI) const;
Expand Down
16 changes: 16 additions & 0 deletions llvm/test/MC/Disassembler/AMDGPU/decode-err.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# RUN: llvm-mc -triple=amdgpu9.00 -disassemble -filetype=null < %s 2>&1 | FileCheck -check-prefix=GCN-ERR %s
# RUN: llvm-mc -triple=amdgpu9.50 -disassemble -filetype=null < %s 2>&1 | FileCheck -check-prefix=GFX950-ERR %s
# RUN: llvm-mc -triple=amdgpu11.00 -disassemble -show-encoding < %s | FileCheck -check-prefixes=W32 %s
# RUN: llvm-mc -triple=amdgpu11.00 -mattr=+wavefrontsize64 -disassemble -show-encoding < %s 2>&1 | FileCheck -check-prefixes=W64 %s
# RUN: llvm-mc -triple=amdgpu12.00 -disassemble -filetype=null < %s 2>&1 | FileCheck -check-prefix=GFX12-ERR %s
Expand Down Expand Up @@ -109,6 +110,21 @@
# GFX90A: [[@LINE+1]]:1: warning: invalid instruction encoding
0x00,0x00,0x6d,0xd8,0x01,0x00,0x00,0x00

# The f8f6f4 source tuples are narrowed down according to cbsz/blgp, but ttmp
# registers have no 192-bit tuple.
# GFX950-ERR: [[@LINE+1]]:1: warning: invalid instruction encoding
0x00,0x00,0xae,0xd3,0x00,0xe9,0x00,0x64

# Same, except that the source selector is an inline constant, which is not a
# register at all.
# GFX950-ERR: [[@LINE+1]]:1: warning: invalid instruction encoding
0x00,0x00,0xae,0xd3,0xf2,0x00,0x02,0x64

# The wmma source tuples are narrowed down according to the matrix formats, but
# scalar registers have no 384-bit tuple.
# GFX1250-ERR: [[@LINE+1]]:1: warning: invalid instruction encoding
0x00,0x18,0x33,0xcc,0x08,0x30,0xa2,0x04
Comment on lines +123 to +126

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like there are 3 size error cases, but only 2 size error tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only 12 could fail here.


# This encoding references a missing trailing literal.
# GFX1250-ERR: [[@LINE+1]]:1: warning: invalid instruction encoding
0x00,0x00,0x33,0xcc,0xff,0x68,0x02,0x02
Loading