[clang] [llvm] [RISCV][MC] add experimental `Zvvfmm` MC support (PR #196486)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 01:26:23 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver
Author: Kiva (imkiva)
<details>
<summary>Changes</summary>
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.
---
Patch is 23.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/196486.diff
14 Files Affected:
- (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1)
- (modified) llvm/docs/RISCVUsage.rst (+4-1)
- (modified) llvm/docs/ReleaseNotes.md (+1)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+59)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp (+11)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h (+2)
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+9-1)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+1-1)
- (added) llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td (+109)
- (removed) llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td (-37)
- (modified) llvm/test/CodeGen/RISCV/features-info.ll (+1)
- (added) llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s (+94)
- (added) llvm/test/MC/RISCV/rvv/zvvfmm.s (+57)
- (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+1)
``````````diff
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)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 2c8805f5fe796..9612f239c516d 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -362,8 +362,11 @@ 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/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`.
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/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index cbf3d0f518ac8..1b2742c76da05 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;
@@ -3903,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();
@@ -3939,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/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/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/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
new file mode 100644
index 0000000000000..5425ce391e8aa
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// 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,
+ "$vd, $vs1, $vs2"> {
+ let mayLoad = 0;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Constraints = "$vd = $vd_wb";
+ let vm = 1;
+ let VMConstraint = false;
+}
+
+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;
+}
+
+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/lib/Target/RISCV/RISCVInstrInfoZvvmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
deleted file mode 100644
index d7620bf072ac3..0000000000000
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
+++ /dev/null
@@ -1,37 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// 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.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Instructions
-//===----------------------------------------------------------------------===//
-
-class VIMEMACVV<bits<6> funct6, string opcodestr>
- : RVInstVV<funct6, OPIVV, (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 vm = 1;
- 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]
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..8f5f10ef2d6bd
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
@@ -0,0 +1,94 @@
+# 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
+
+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: 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: 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
+
+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
+
+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
+
+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
+
+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
+
+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
+
+vf8wimmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: expected '.scale' suffix
+# C...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/196486
More information about the cfe-commits
mailing list