diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp index d05997cacba0a..ca1ec70327ff2 100644 --- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -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); @@ -1065,33 +1065,50 @@ 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 @@ -1099,11 +1116,11 @@ static void adjustMFMA_F8F6F4OpRegClass(const MCRegisterInfo &MRI, /// 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); @@ -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); @@ -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 { diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h index d0859d144722f..16019611120cf 100644 --- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h +++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h @@ -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; diff --git a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt index de9bf7bac9548..e9537d1ec6c24 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt @@ -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 @@ -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 + # This encoding references a missing trailing literal. # GFX1250-ERR: [[@LINE+1]]:1: warning: invalid instruction encoding 0x00,0x00,0x33,0xcc,0xff,0x68,0x02,0x02