[llvm] e337de1 - [AMDGPU][MC] Fix out-of-range MFMA tuple register-name assertion (#215147)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 9 19:04:44 PDT 2026
Author: Shilei Tian
Date: 2026-08-09T22:04:39-04:00
New Revision: e337de11042692af6873a4ba13aa60aeba52900e
URL: https://github.com/llvm/llvm-project/commit/e337de11042692af6873a4ba13aa60aeba52900e
DIFF: https://github.com/llvm/llvm-project/commit/e337de11042692af6873a4ba13aa60aeba52900e.diff
LOG: [AMDGPU][MC] Fix out-of-range MFMA tuple register-name assertion (#215147)
Fixes #215007.
Added:
Modified:
llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
llvm/test/MC/Disassembler/AMDGPU/decode-err.txt
Removed:
################################################################################
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
diff erent 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
More information about the llvm-commits
mailing list