[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