[clang] [llvm] [RISCV][MC] add experimental `Zvvfmm` MC support (PR #196486)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 01:25:39 PDT 2026
https://github.com/imkiva created https://github.com/llvm/llvm-project/pull/196486
This PR adds experimental MC layer support for the RISC-V `Zvvfmm` from Integrated Matrix Extension based on the [riscv-isa-release-fa55752-2026-05-04 spec release](https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04).
This PR:
- Renames `RISCVInstrInfoZvvmm.td` to `RISCVInstrInfoZvvm.td` so `Zvvmm` and `Zvvfmm` share the same IME instruction file according to the spec. And all future instructions from the `Zvvm family` will be placed here too.
- Adds a new `VScaleReg` asm operand to support the `v0.scale` assembly syntax.
- Adds assembler support for floating-point matrix instructions: `vfmmacc.vv`, `vfwmmacc.vv`, `vfqmmacc.vv`, `vf8wmmacc.vv`
- Adds integer-input floating-point accumulate scaled instructions: `vfwimmacc.vv`, `vfqimmacc.vv`, `vf8wimmacc.vv`
Note: microscaling individual extension names (like `Zvvxi*mm`, `Zvvxni*mm`) are not implemented yet in this PR, so everything is currently gated by `+experimental-zvvfmm` flag.
>From 04b7de7432ee3ab21e0486e187a57614059fc05a Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Wed, 6 May 2026 13:23:19 +0800
Subject: [PATCH 1/5] [RISCV][MC] add experimental `Zvvfmm` support
---
llvm/docs/RISCVUsage.rst | 3 ++
llvm/docs/ReleaseNotes.md | 1 +
llvm/lib/Target/RISCV/RISCVFeatures.td | 10 ++++++-
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +-
...nstrInfoZvvmm.td => RISCVInstrInfoZvvm.td} | 28 ++++++++++++++++---
llvm/test/CodeGen/RISCV/features-info.ll | 1 +
llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 18 ++++++++++++
llvm/test/MC/RISCV/rvv/zvvfmm.s | 27 ++++++++++++++++++
.../TargetParser/RISCVISAInfoTest.cpp | 1 +
9 files changed, 85 insertions(+), 6 deletions(-)
rename llvm/lib/Target/RISCV/{RISCVInstrInfoZvvmm.td => RISCVInstrInfoZvvm.td} (61%)
create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm.s
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 2c8805f5fe796..95804ef711aa9 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -362,6 +362,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zvzip``
LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__.
+``experimental-zvvfmm``
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/fa5575203a2dc2e086bc4edc9de7fd9439816488/src/integrated-matrix.adoc>`__.
+
``experimental-zvvmm``
LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 424e67b8b4235..fce48e0395c2f 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -202,6 +202,7 @@ Makes programs 10x faster by doing Special New Thing.
* `-mcpu=sifive-x160` and `-mcpu=sifive-x180` were added.
* Support for the experimental `XRivosVisni` vendor extension has been removed.
* Adds experimental assembler support for the 'Zvvmm` (RISC-V Integer Matrix Multiply-Accumulate) extension.
+* Adds experimental assembler support for the 'Zvvfmm` (RISC-V Floating-Point Matrix Multiply-Accumulate) extension.
### Changes to the WebAssembly Backend
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index b905870a482ff..72735dfce0867 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -893,6 +893,15 @@ def HasStdExtZvvmm : Predicate<"Subtarget->hasStdExtZvvmm()">,
AssemblerPredicate<(all_of FeatureStdExtZvvmm),
"'Zvvmm' (Integer Matrix Multiply-Accumulate)">;
+// Integrated Matrix Extension floating-point matrix multiply-accumulate
+def FeatureStdExtZvvfmm
+ : RISCVExperimentalExtension<0, 1,
+ "Floating-Point Matrix Multiply-Accumulate",
+ [FeatureStdExtZve32f]>;
+def HasStdExtZvvfmm : Predicate<"Subtarget->hasStdExtZvvfmm()">,
+ AssemblerPredicate<(all_of FeatureStdExtZvvfmm),
+ "'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate)">;
+
// Vector instruction predicates
def HasVInstructions : Predicate<"Subtarget->hasVInstructions()">,
@@ -2072,4 +2081,3 @@ def TuneSiFive7 : SubtargetFeature<"sifive7", "RISCVProcFamily", "SiFive7",
def TuneVentanaVeyron : SubtargetFeature<"ventana-veyron", "RISCVProcFamily", "VentanaVeyron",
"Ventana Veyron-Series processors">;
-
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 3295d18a2d352..541bf302bf8e5 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2356,7 +2356,7 @@ include "RISCVInstrInfoZvk.td"
include "RISCVInstrInfoZvdot4a8i.td"
include "RISCVInstrInfoZvfofp8min.td"
include "RISCVInstrInfoZvzip.td"
-include "RISCVInstrInfoZvvmm.td"
+include "RISCVInstrInfoZvvm.td"
// Packed SIMD
include "RISCVInstrInfoP.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
similarity index 61%
rename from llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
rename to llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index d7620bf072ac3..1334eda8e7b44 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -6,10 +6,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file describes the RISC-V instructions from the standard 'Zvvmm'
-// extension for integer matrix multiply-accumulate.
-// This version is still experimental as the 'Zvvmm' extension hasn't been
-// ratified yet.
+// This file describes the RISC-V instructions from the standard 'Zvvm' family
+// of Integrated Matrix extensions.
+// These extensions are still experimental as they haven't been ratified yet.
//
//===----------------------------------------------------------------------===//
@@ -35,3 +34,24 @@ let Predicates = [HasStdExtZvvmm] in {
def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">;
def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">;
} // Predicates = [HasStdExtZvvmm]
+
+class VFMEMACVV<bits<6> funct6, string opcodestr>
+ : RVInstVV<funct6, OPFVV, (outs VR:$vd_wb),
+ (ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
+ "$vd, $vs1, $vs2"> {
+ let mayLoad = 0;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Constraints = "$vd = $vd_wb";
+ let Uses = [FRM, VL, VTYPE];
+ let mayRaiseFPException = true;
+ let vm = 1;
+ let VMConstraint = false;
+}
+
+let Predicates = [HasStdExtZvvfmm] in {
+ def VFMMACC_VV : VFMEMACVV<0b010100, "vfmmacc.vv">;
+ def VFWMMACC_VV : VFMEMACVV<0b010101, "vfwmmacc.vv">;
+ def VFQMMACC_VV : VFMEMACVV<0b010110, "vfqmmacc.vv">;
+ def VF8WMMACC_VV : VFMEMACVV<0b010111, "vf8wmmacc.vv">;
+} // Predicates = [HasStdExtZvvfmm]
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 92e033cb90dc9..486eaec0cba30 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -39,6 +39,7 @@
; CHECK-NEXT: experimental-zvfbfa - 'Zvfbfa' (Additional BF16 vector compute support).
; CHECK-NEXT: experimental-zvfofp8min - 'Zvfofp8min' (Vector OFP8 Converts).
; CHECK-NEXT: experimental-zvkgs - 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography).
+; CHECK-NEXT: experimental-zvvfmm - 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate).
; CHECK-NEXT: experimental-zvvmm - 'Zvvmm' (Integer Matrix Multiply-Accumulate).
; CHECK-NEXT: experimental-zvzip - 'Zvzip' (Vector Reordering Structured Data).
; CHECK-NEXT: f - 'F' (Single-Precision Floating-Point).
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
new file mode 100644
index 0000000000000..7f00b757fa87b
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
@@ -0,0 +1,18 @@
+# RUN: not llvm-mc -triple=riscv64 --mattr=+experimental-zvvfmm %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+
+vfmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t
+
+vfwmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v0.t
+
+vfqmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v0.t
+
+vf8wmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v0.t
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm.s b/llvm/test/MC/RISCV/rvv/zvvfmm.s
new file mode 100644
index 0000000000000..3b398e88f7f7b
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm.s
@@ -0,0 +1,27 @@
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvfmm %s \
+# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvfmm %s \
+# RUN: | llvm-objdump -d --mattr=+experimental-zvvfmm - \
+# RUN: | FileCheck %s --check-prefix=CHECK-INST
+
+vfmmacc.vv v8, v4, v20
+# CHECK-INST: vfmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x14,0x42,0x53]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vfwmmacc.vv v8, v4, v20
+# CHECK-INST: vfwmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x14,0x42,0x57]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vfqmmacc.vv v8, v4, v20
+# CHECK-INST: vfqmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x14,0x42,0x5b]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vf8wmmacc.vv v8, v4, v20
+# CHECK-INST: vf8wmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x14,0x42,0x5f]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index e96e2d9d462dc..fcacbe80a271f 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1384,6 +1384,7 @@ Experimental extensions
zvfbfa 0.1
zvfofp8min 0.2
zvkgs 0.7
+ zvvfmm 0.1
zvvmm 0.1
zvzip 0.1
smpmpmt 0.6
>From 5bb19ad8c680fe3d7fc9884c46c807319d98d1e1 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Wed, 6 May 2026 22:49:34 +0800
Subject: [PATCH 2/5] [RISCV][MC] add basic microscaling instructions
---
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 21 ++++++
.../RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 11 ++++
.../RISCV/MCTargetDesc/RISCVInstPrinter.h | 2 +
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 66 +++++++++++++++++--
llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 58 +++++++++++++++-
llvm/test/MC/RISCV/rvv/zvvfmm.s | 30 +++++++++
6 files changed, 178 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index cbf3d0f518ac8..ddee58bb973d2 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -206,6 +206,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseJALOffset(OperandVector &Operands);
ParseStatus parseVTypeI(OperandVector &Operands);
ParseStatus parseMaskReg(OperandVector &Operands);
+ ParseStatus parseVScaleReg(OperandVector &Operands);
ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
ParseStatus parseGPRAsFPR(OperandVector &Operands);
@@ -2522,6 +2523,26 @@ ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
return ParseStatus::Success;
}
+ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
+ if (getLexer().isNot(AsmToken::Identifier))
+ return ParseStatus::NoMatch;
+
+ StringRef Name = getLexer().getTok().getIdentifier();
+ if (!Name.consume_back(".scale"))
+ return Error(getLoc(), "expected '.scale' suffix");
+ MCRegister Reg = matchRegisterNameHelper(Name);
+
+ if (!Reg)
+ return ParseStatus::NoMatch;
+ if (Reg != RISCV::V0)
+ return ParseStatus::NoMatch;
+ SMLoc S = getLoc();
+ SMLoc E = getTok().getEndLoc();
+ getLexer().Lex();
+ Operands.push_back(RISCVOperand::createReg(Reg, S, E));
+ return ParseStatus::Success;
+}
+
ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
return ParseStatus::NoMatch;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index b381b8f7147fc..e2416f832aecc 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -341,6 +341,17 @@ void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo,
O << ".t";
}
+void RISCVInstPrinter::printVScaleReg(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(OpNo);
+
+ assert(MO.isReg() && "printVScaleReg can only print register operands");
+ O << ", ";
+ printRegName(O, MO.getReg());
+ O << ".scale";
+}
+
void RISCVInstPrinter::printImm(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
index 17469bd87e34e..fb0598faff2be 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -52,6 +52,8 @@ class RISCVInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printVMaskReg(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
+ void printVScaleReg(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printImm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
void printRegList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index 1334eda8e7b44..5425ce391e8aa 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -16,6 +16,24 @@
// Instructions
//===----------------------------------------------------------------------===//
+def VScaleAsmOperand : AsmOperandClass {
+ let Name = "RVVScaleRegOpOperand";
+ let RenderMethod = "addRegOperands";
+ let PredicateMethod = "isV0Reg";
+ let ParserMethod = "parseVScaleReg";
+ let DiagnosticType = "InvalidVScaleRegister";
+ let DiagnosticString = "operand must be v0.scale";
+}
+
+// An always present v0.scale operand encoded with vm=0. Classes that use this
+// must set the vm field in RVInstV* to 0.
+def VScaleOp : RegisterOperand<VMV0> {
+ let ParserMatchClass = VScaleAsmOperand;
+ let PrintMethod = "printVScaleReg";
+ let EncoderMethod = "getVMaskReg";
+ let DecoderMethod = "decodeVMaskReg";
+}
+
class VIMEMACVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
@@ -28,13 +46,6 @@ class VIMEMACVV<bits<6> funct6, string opcodestr>
let VMConstraint = false;
}
-let Predicates = [HasStdExtZvvmm] in {
- def VMMACC_VV : VIMEMACVV<0b111000, "vmmacc.vv">;
- def VWMMACC_VV : VIMEMACVV<0b111001, "vwmmacc.vv">;
- def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">;
- def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">;
-} // Predicates = [HasStdExtZvvmm]
-
class VFMEMACVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPFVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
@@ -49,9 +60,50 @@ class VFMEMACVV<bits<6> funct6, string opcodestr>
let VMConstraint = false;
}
+class VFMEMACScaleVV<bits<6> funct6, string opcodestr>
+ : RVInstVV<funct6, OPFVV, (outs VR:$vd_wb),
+ (ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr,
+ "$vd, $vs1, $vs2$vm"> {
+ let mayLoad = 0;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Constraints = "$vd = $vd_wb";
+ let Uses = [FRM, VL, VTYPE];
+ let mayRaiseFPException = true;
+ let vm = 0;
+ let VMConstraint = false;
+}
+
+class VIFMEMACScaleVV<bits<6> funct6, string opcodestr>
+ : RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
+ (ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr,
+ "$vd, $vs1, $vs2$vm"> {
+ let mayLoad = 0;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Constraints = "$vd = $vd_wb";
+ let Uses = [FRM, VL, VTYPE];
+ let mayRaiseFPException = true;
+ let vm = 0;
+ let VMConstraint = false;
+}
+
+let Predicates = [HasStdExtZvvmm] in {
+ def VMMACC_VV : VIMEMACVV<0b111000, "vmmacc.vv">;
+ def VWMMACC_VV : VIMEMACVV<0b111001, "vwmmacc.vv">;
+ def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">;
+ def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">;
+} // Predicates = [HasStdExtZvvmm]
+
let Predicates = [HasStdExtZvvfmm] in {
def VFMMACC_VV : VFMEMACVV<0b010100, "vfmmacc.vv">;
def VFWMMACC_VV : VFMEMACVV<0b010101, "vfwmmacc.vv">;
def VFQMMACC_VV : VFMEMACVV<0b010110, "vfqmmacc.vv">;
def VF8WMMACC_VV : VFMEMACVV<0b010111, "vf8wmmacc.vv">;
+ def VFWMMACC_VV_SCALE : VFMEMACScaleVV<0b010101, "vfwmmacc.vv">;
+ def VFQMMACC_VV_SCALE : VFMEMACScaleVV<0b010110, "vfqmmacc.vv">;
+ def VF8WMMACC_VV_SCALE : VFMEMACScaleVV<0b010111, "vf8wmmacc.vv">;
+ def VFWIMMACC_VV : VIFMEMACScaleVV<0b111001, "vfwimmacc.vv">;
+ def VFQIMMACC_VV : VIFMEMACScaleVV<0b111010, "vfqimmacc.vv">;
+ def VF8WIMMACC_VV : VIFMEMACScaleVV<0b111011, "vf8wimmacc.vv">;
} // Predicates = [HasStdExtZvvfmm]
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
index 7f00b757fa87b..b510195591bf5 100644
--- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
@@ -5,14 +5,66 @@ vfmmacc.vv v8, v4, v20, v0.t
# CHECK-ERROR: invalid operand for instruction
# CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t
-vfwmmacc.vv v8, v4, v20, v0.t
+vfmmacc.vv v8, v4, v20, v0.scale
# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.scale
+
+vfwmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: expected '.scale' suffix
# CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v0.t
+vfwmmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v1.scale
+
vfqmmacc.vv v8, v4, v20, v0.t
-# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR: expected '.scale' suffix
# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v0.t
+vfqmmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v1.scale
+
vf8wmmacc.vv v8, v4, v20, v0.t
-# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR: expected '.scale' suffix
# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v0.t
+
+vf8wmmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v1.scale
+
+vfwimmacc.vv v8, v4, v20
+# CHECK-ERROR: too few operands for instruction
+# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20
+
+vfwimmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: expected '.scale' suffix
+# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v0.t
+
+vfwimmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v1.scale
+
+vfqimmacc.vv v8, v4, v20
+# CHECK-ERROR: too few operands for instruction
+# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20
+
+vfqimmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: expected '.scale' suffix
+# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v0.t
+
+vfqimmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v1.scale
+
+vf8wimmacc.vv v8, v4, v20
+# CHECK-ERROR: too few operands for instruction
+# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20
+
+vf8wimmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: expected '.scale' suffix
+# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v0.t
+
+vf8wimmacc.vv v8, v4, v20, v1.scale
+# CHECK-ERROR: operand must be v0.scale
+# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v1.scale
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm.s b/llvm/test/MC/RISCV/rvv/zvvfmm.s
index 3b398e88f7f7b..4c6a60d5b3fff 100644
--- a/llvm/test/MC/RISCV/rvv/zvvfmm.s
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm.s
@@ -16,12 +16,42 @@ vfwmmacc.vv v8, v4, v20
# CHECK-ENCODING: [0x57,0x14,0x42,0x57]
# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+vfwmmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vfwmmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x14,0x42,0x55]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
vfqmmacc.vv v8, v4, v20
# CHECK-INST: vfqmmacc.vv v8, v4, v20
# CHECK-ENCODING: [0x57,0x14,0x42,0x5b]
# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+vfqmmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vfqmmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x14,0x42,0x59]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
vf8wmmacc.vv v8, v4, v20
# CHECK-INST: vf8wmmacc.vv v8, v4, v20
# CHECK-ENCODING: [0x57,0x14,0x42,0x5f]
# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vf8wmmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vf8wmmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x14,0x42,0x5d]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vfwimmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vfwimmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe5]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vfqimmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vfqimmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe9]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
+
+vf8wimmacc.vv v8, v4, v20, v0.scale
+# CHECK-INST: vf8wimmacc.vv v8, v4, v20, v0.scale
+# CHECK-ENCODING: [0x57,0x04,0x42,0xed]
+# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}}
>From 36e787aba9ab48e6afbabe9d7cdd782898bbb314 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 8 May 2026 15:16:24 +0800
Subject: [PATCH 3/5] [RISCV][MC] check if v0.scale overlaps vs1, vs2, vd
---
llvm/docs/RISCVUsage.rst | 2 +-
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 38 +++++++++++++++++++
llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 24 ++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 95804ef711aa9..47a6c2d190e3e 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -363,7 +363,7 @@ The primary goal of experimental support is to assist in the process of ratifica
LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__.
``experimental-zvvfmm``
- LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/fa5575203a2dc2e086bc4edc9de7fd9439816488/src/integrated-matrix.adoc>`__.
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__.
``experimental-zvvmm``
LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__.
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index ddee58bb973d2..1b2742c76da05 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -3924,6 +3924,20 @@ unsigned getLMULFromVectorRegister(MCRegister Reg) {
return 1;
}
+static bool isZvvfmmScaleOpcode(unsigned Opcode) {
+ switch (Opcode) {
+ case RISCV::VFWMMACC_VV_SCALE:
+ case RISCV::VFQMMACC_VV_SCALE:
+ case RISCV::VF8WMMACC_VV_SCALE:
+ case RISCV::VFWIMMACC_VV:
+ case RISCV::VFQIMMACC_VV:
+ case RISCV::VF8WIMMACC_VV:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool RISCVAsmParser::validateInstruction(MCInst &Inst,
OperandVector &Operands) {
unsigned Opcode = Inst.getOpcode();
@@ -3960,6 +3974,30 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst,
}
}
+ if (isZvvfmmScaleOpcode(Opcode)) {
+ auto CheckOperandDoesNotOverlapV0 = [&](int OperandIdx,
+ unsigned ParsedIdx) {
+ if (Inst.getOperand(OperandIdx).getReg() == RISCV::V0)
+ return Error(Operands[ParsedIdx]->getStartLoc(),
+ "vd, vs1, and vs2 cannot overlap v0.scale");
+ return false;
+ };
+
+ int DestIdx =
+ RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
+ int VS1Idx =
+ RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
+ int VS2Idx =
+ RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
+ assert(DestIdx >= 0 && VS1Idx >= 0 && VS2Idx >= 0 &&
+ "Unexpected Zvvfmm scaled operand list");
+
+ if (CheckOperandDoesNotOverlapV0(DestIdx, 1) ||
+ CheckOperandDoesNotOverlapV0(VS1Idx, 2) ||
+ CheckOperandDoesNotOverlapV0(VS2Idx, 3))
+ return true;
+ }
+
const MCInstrDesc &MCID = MII.get(Opcode);
if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
return false;
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
index b510195591bf5..8f5f10ef2d6bd 100644
--- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
@@ -33,6 +33,18 @@ vf8wmmacc.vv v8, v4, v20, v1.scale
# CHECK-ERROR: operand must be v0.scale
# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v1.scale
+vfwmmacc.vv v0, v4, v20, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vfwmmacc.vv v0, v4, v20, v0.scale
+
+vfqmmacc.vv v8, v0, v20, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v0, v20, v0.scale
+
+vf8wmmacc.vv v8, v4, v0, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v0, v0.scale
+
vfwimmacc.vv v8, v4, v20
# CHECK-ERROR: too few operands for instruction
# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20
@@ -45,6 +57,10 @@ vfwimmacc.vv v8, v4, v20, v1.scale
# CHECK-ERROR: operand must be v0.scale
# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v1.scale
+vfwimmacc.vv v0, v4, v20, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vfwimmacc.vv v0, v4, v20, v0.scale
+
vfqimmacc.vv v8, v4, v20
# CHECK-ERROR: too few operands for instruction
# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20
@@ -57,6 +73,10 @@ vfqimmacc.vv v8, v4, v20, v1.scale
# CHECK-ERROR: operand must be v0.scale
# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v1.scale
+vfqimmacc.vv v8, v0, v20, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v0, v20, v0.scale
+
vf8wimmacc.vv v8, v4, v20
# CHECK-ERROR: too few operands for instruction
# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20
@@ -68,3 +88,7 @@ vf8wimmacc.vv v8, v4, v20, v0.t
vf8wimmacc.vv v8, v4, v20, v1.scale
# CHECK-ERROR: operand must be v0.scale
# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v1.scale
+
+vf8wimmacc.vv v8, v4, v0, v0.scale
+# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale
+# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v0, v0.scale
>From b315d2b9d4a3b8cff460ee0ec3bdba3a3107e574 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 8 May 2026 15:18:41 +0800
Subject: [PATCH 4/5] Update docs
---
llvm/docs/RISCVUsage.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 47a6c2d190e3e..9612f239c516d 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -366,7 +366,7 @@ The primary goal of experimental support is to assist in the process of ratifica
LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__.
``experimental-zvvmm``
- LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__.
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__.
To use an experimental extension from `clang`, you must add `-menable-experimental-extensions` to the command line, and specify the exact version of the experimental extension you are using. To use an experimental extension with LLVM's internal developer tools (e.g. `llc`, `llvm-objdump`, `llvm-mc`), you must prefix the extension name with `experimental-`. Note that you don't need to specify the version with internal tools, and shouldn't include the `experimental-` prefix with `clang`.
>From c633cf4364b60a62ab71609232a8418c5f2c3c35 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 8 May 2026 16:24:55 +0800
Subject: [PATCH 5/5] Update tests
---
clang/test/Driver/print-supported-extensions-riscv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 83920246d5dad..393b07edb0c99 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -253,6 +253,7 @@
// CHECK-NEXT: zvfbfa 0.1 'Zvfbfa' (Additional BF16 vector compute support)
// CHECK-NEXT: zvfofp8min 0.2 'Zvfofp8min' (Vector OFP8 Converts)
// CHECK-NEXT: zvkgs 0.7 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography)
+// CHECK-NEXT: zvvfmm 0.1 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate)
// CHECK-NEXT: zvvmm 0.1 'Zvvmm' (Integer Matrix Multiply-Accumulate)
// CHECK-NEXT: zvzip 0.1 'Zvzip' (Vector Reordering Structured Data)
// CHECK-NEXT: smpmpmt 0.6 'Smpmpmt' (PMP-based Memory Types Extension)
More information about the cfe-commits
mailing list