https://github.com/imkiva updated 
https://github.com/llvm/llvm-project/pull/196486

>From 2f8fb98529fb12db614abc780434b1a558bd9364 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Wed, 6 May 2026 13:23:19 +0800
Subject: [PATCH 1/7] [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 2b68827e7b136..4824dcd3c99e5 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -363,6 +363,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 ec613d64e20a3..57e7812284991 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -203,6 +203,7 @@ Makes programs 10x faster by doing Special New Thing.
 * 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 support for 'Ziccid' (Instruction/Data Coherence and Consistency) 
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 a92fb63e3c3cd..852311579d1c2 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -897,6 +897,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()">,
@@ -2076,4 +2085,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 d4b920c08a096..96f193a2633f5 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 d28066d423b77..cd0dcf98f50de 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1385,6 +1385,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 e139e82c3125fb5be29aa498059f5d7c05bdd4c4 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Wed, 6 May 2026 22:49:34 +0800
Subject: [PATCH 2/7] [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 f7640e8f1bdbf1fd2fd9b9871c4ba782deb7d8c2 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 8 May 2026 15:16:24 +0800
Subject: [PATCH 3/7] [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 4824dcd3c99e5..7df6ef78c27ac 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -364,7 +364,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 9a2f80a4ef8c6980a78ac46568b9cf1cafa4ddc1 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 8 May 2026 15:18:41 +0800
Subject: [PATCH 4/7] 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 7df6ef78c27ac..71d91f73383b5 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -367,7 +367,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 1f29305e7eb9603facaf6d23ff181e7f79891441 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 8 May 2026 16:24:55 +0800
Subject: [PATCH 5/7] 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 d0a773f8f43d8..82ef3e54dab29 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -254,6 +254,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)

>From 3382f6308efa3af75bb58cd9f7072adba1843924 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 8 May 2026 16:50:59 +0800
Subject: [PATCH 6/7] Update comments

---
 llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index 5425ce391e8aa..0a358ba9ba0bb 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -103,6 +103,10 @@ let Predicates = [HasStdExtZvvfmm] in {
   def VFWMMACC_VV_SCALE : VFMEMACScaleVV<0b010101, "vfwmmacc.vv">;
   def VFQMMACC_VV_SCALE : VFMEMACScaleVV<0b010110, "vfqmmacc.vv">;
   def VF8WMMACC_VV_SCALE : VFMEMACScaleVV<0b010111, "vf8wmmacc.vv">;
+  // FIXME: The integer-input MX forms should be gated by the
+  // Zvvxi*/Zvvxni* microscaling extensions once LLVM models those
+  // individual extension names. They are temporarily enabled under
+  // experimental-zvvfmm for MC bring-up.
   def VFWIMMACC_VV : VIFMEMACScaleVV<0b111001, "vfwimmacc.vv">;
   def VFQIMMACC_VV : VIFMEMACScaleVV<0b111010, "vfqimmacc.vv">;
   def VF8WIMMACC_VV : VIFMEMACScaleVV<0b111011, "vf8wimmacc.vv">;

>From c4085a48cb8d94ada6524d2ab56f040012f1b3f0 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 8 May 2026 16:56:35 +0800
Subject: [PATCH 7/7] More tests

---
 llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s | 9 +++++++++
 llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s          | 1 +
 2 files changed, 10 insertions(+)
 create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s

diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s 
b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s
new file mode 100644
index 0000000000000..239153b62c233
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s
@@ -0,0 +1,9 @@
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvfmm %s \
+# RUN:        | llvm-objdump -d --mattr=+experimental-zvvfmm - \
+# RUN:        | FileCheck %s
+
+# vm=0 is reserved for non-widening vfmmacc.vv, so this raw encoding must not
+# decode as a scaled vfmmacc form.
+.insn 0x4, 0x51421457
+# CHECK: <unknown>
+# CHECK-NOT: vfmmacc.vv
diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s 
b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
index 8f5f10ef2d6bd..ccb1e7ebcd12d 100644
--- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
+++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s
@@ -5,6 +5,7 @@ vfmmacc.vv v8, v4, v20, v0.t
 # CHECK-ERROR: invalid operand for instruction
 # CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t
 
+# vm=0 is reserved for non-widening vfmmacc.vv.
 vfmmacc.vv v8, v4, v20, v0.scale
 # CHECK-ERROR: invalid operand for instruction
 # CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.scale

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to