Repository: llvm/llvm-project
Pull request #133031: [RISCV] Add MC layer support for XSfmm*.
Author: login: topperc
Labels: name: clang
description: Clang issues not falling into any other category
name: backend:RISC-V
name: clang:driver
description: 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'
name: llvm:mc
description: Machine (object) code
Created: 2025-03-26T03:17:09Z | Merged: 2025-05-21T15:26:36Z

This adds assembler/disassembler support for XSfmmbase 0.6 and related SiFive matrix multiplication extensions based on the spec here https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification

Functionality-wise, this is the same as the Zvma extension proposal that SiFive shared with the Attached Matrix Extension Task Group. The extension names and instruction mnemonics have been changed to use vendor prefixes.

Note this is a non-conforming extension as the opcodes used here are in the standard opcode space in OP-V or OP-VE.


Diff:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index bd3c1b7de743a..7b4f46cdb4443 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -170,6 +170,16 @@
 // CHECK-NEXT:     xmipscmov            1.0       'XMIPSCMov' (MIPS conditional move instruction (mips.ccmov))
 // CHECK-NEXT:     xmipslsp             1.0       'XMIPSLSP' (MIPS optimization for hardware load-store bonding)
 // CHECK-NEXT:     xsfcease             1.0       'XSfcease' (SiFive sf.cease Instruction)
+// CHECK-NEXT:     xsfmm128t            0.6       'XSfmm128t' (TE=128 configuration)
+// CHECK-NEXT:     xsfmm16t             0.6       'XSfmm16t' (TE=16 configuration)
+// CHECK-NEXT:     xsfmm32a16f          0.6       'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF))
+// CHECK-NEXT:     xsfmm32a32f          0.6       'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b)
+// CHECK-NEXT:     xsfmm32a8f           0.6       'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)
+// CHECK-NEXT:     xsfmm32a8i           0.6       'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)
+// CHECK-NEXT:     xsfmm32t             0.6       'XSfmm32t' (TE=32 configuration)
+// CHECK-NEXT:     xsfmm64a64f          0.6       'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)
+// CHECK-NEXT:     xsfmm64t             0.6       'XSfmm64t' (TE=64 configuration)
+// CHECK-NEXT:     xsfmmbase            0.6       'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)
 // CHECK-NEXT:     xsfvcp               1.0       'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)
 // CHECK-NEXT:     xsfvfnrclipxfqf      1.0       'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)
 // CHECK-NEXT:     xsfvfwmaccqqq        1.0       'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))
diff --git a/clang/test/Preprocessor/riscv-target-features-sifive.c b/clang/test/Preprocessor/riscv-target-features-sifive.c
new file mode 100644
index 0000000000000..e4c03876bd94b
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-target-features-sifive.c
@@ -0,0 +1,79 @@
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm128t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm128t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// CHECK-XSFMM128T: __riscv_xsfmm128t  6000{{$}}
+//
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm16t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm16t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// CHECK-XSFMM16T: __riscv_xsfmm16t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm32a8i -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm32a8i -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// CHECK-XSFMM32a8I: __riscv_xsfmm32a8i  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm32a8f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm32a8f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// CHECK-XSFMM32A8F: __riscv_xsfmm32a8f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm32a16f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm32a16f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// CHECK-XSFMM32a16F: __riscv_xsfmm32a16f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm32a32f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm32a32f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// CHECK-XSFMM32a32F: __riscv_xsfmm32a32f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm32t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm32t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// CHECK-XSFMM32T: __riscv_xsfmm32t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm64a64f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm64a64f -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// CHECK-XSFMM64a64f: __riscv_xsfmm64a64f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmm64t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmm64t -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// CHECK-XSFMM64T: __riscv_xsfmm64t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zve32x_xsfmmbase -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zve32x_xsfmmbase -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// CHECK-XSFMMBASE: __riscv_xsfmmbase  6000{{$}}
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index cf11d3878a745..b8bec547c06b6 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -392,6 +392,9 @@ The current vendor extensions supported are:
 ``XVentanaCondOps``
   LLVM implements `version 1.0.0 of the VTx-family custom instructions specification <https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf>`__ by Ventana Micro Systems.  All instructions are prefixed with `vt.` as described in the specification, and the riscv-toolchain-convention document linked above.  These instructions are only available for riscv64 at this time.
 
+``Xsfmm*``
+  LLVM implements `version 0.6 of the Xsfmm Family of Attached Matrix Extensions Specification <https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification>`__ by SiFive.  All instructions are prefixed with `sf.` as described in the specification.
+
 ``XSfvcp``
   LLVM implements `version 1.1.0 of the SiFive Vector Coprocessor Interface (VCIX) Software Specification <https://sifive.cdn.prismic.io/sifive/Zn3m1R5LeNNTwnLS_vcix-spec-software-v1p1.pdf>`__ by SiFive.  All instructions are prefixed with `sf.vc.` as described in the specification, and the riscv-toolchain-convention document linked above.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 590597faaa05f..2f6d90cdc589f 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -197,7 +197,9 @@ Changes to the RISC-V Backend
 * Adds assembler support for the Andes `XAndesvdot` (Andes Vector Dot Product extension).
 * Adds assembler support for the standard `Q` (Quad-Precision Floating Point) 
   extension.
-  
+* Adds experimental assembler support for the SiFive Xsfmm* Attached Matrix
+  Extensions.
+
 Changes to the WebAssembly Backend
 ----------------------------------
 
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index e0105685c210d..a529479b546d9 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -89,6 +89,8 @@ inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
 unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
                      bool MaskAgnostic);
 
+unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
+
 inline static VLMUL getVLMUL(unsigned VType) {
   unsigned VLMul = VType & 0x7;
   return static_cast<VLMUL>(VLMul);
@@ -118,10 +120,34 @@ inline static unsigned getSEW(unsigned VType) {
   return decodeVSEW(VSEW);
 }
 
+inline static unsigned decodeTWiden(unsigned TWiden) {
+  assert((TWiden == 1 || TWiden == 2 || TWiden == 3) &&
+         "Unexpected TWiden value");
+  return 1 << (TWiden - 1);
+}
+
+inline static bool hasXSfmmWiden(unsigned VType) {
+  unsigned TWiden = (VType >> 9) & 0x3;
+  return TWiden != 0;
+}
+
+inline static unsigned getXSfmmWiden(unsigned VType) {
+  unsigned TWiden = (VType >> 9) & 0x3;
+  assert(TWiden != 0 && "Invalid widen value");
+  return 1 << (TWiden - 1);
+}
+
+static inline bool isValidXSfmmVType(unsigned VTypeI) {
+  return (VTypeI & ~0x738) == 0 && RISCVVType::hasXSfmmWiden(VTypeI) &&
+         RISCVVType::getSEW(VTypeI) * RISCVVType::getXSfmmWiden(VTypeI) <= 64;
+}
+
 inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
 
 inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
 
+inline static bool isAltFmt(unsigned VType) { return VType & 0x100; }
+
 void printVType(unsigned VType, raw_ostream &OS);
 
 unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul);
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index f64307babab07..42d6da25805bd 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -125,6 +125,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
                        bool &MaskAgnostic);
   bool generateVTypeError(SMLoc ErrorLoc);
 
+  bool generateXSfmmVTypeError(SMLoc ErrorLoc);
   // Helper to actually emit an instruction to the MCStreamer. Also, when
   // possible, compression of the instruction is performed.
   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
@@ -221,6 +222,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
   }
 
   ParseStatus parseRegReg(OperandVector &Operands);
+  ParseStatus parseXSfmmVType(OperandVector &Operands);
   ParseStatus parseRetval(OperandVector &Operands);
   ParseStatus parseZcmpStackAdj(OperandVector &Operands,
                                 bool ExpectNegative = false);
@@ -634,6 +636,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return isUImm<11>();
   }
 
+  bool isXSfmmVType() const {
+    return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
+  }
+
   /// Return true if the operand is a valid for the fence instruction e.g.
   /// ('iorw').
   bool isFenceArg() const { return Kind == KindTy::Fence; }
@@ -2342,6 +2348,65 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  unsigned Widen = 0;
+  unsigned SEW = 0;
+  bool AltFmt = false;
+  StringRef Identifier;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("e"))
+    goto Fail;
+
+  if (Identifier.getAsInteger(10, SEW)) {
+    if (Identifier != "16alt")
+      goto Fail;
+
+    AltFmt = true;
+    SEW = 16;
+  }
+  if (!RISCVVType::isValidSEW(SEW))
+    goto Fail;
+
+  Lex();
+
+  if (!parseOptionalToken(AsmToken::Comma))
+    goto Fail;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("w"))
+    goto Fail;
+  if (Identifier.getAsInteger(10, Widen))
+    goto Fail;
+  if (Widen != 1 && Widen != 2 && Widen != 4)
+    goto Fail;
+
+  Lex();
+
+  if (getLexer().is(AsmToken::EndOfStatement)) {
+    Operands.push_back(RISCVOperand::createVType(
+        RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
+    return ParseStatus::Success;
+  }
+
+Fail:
+  return generateXSfmmVTypeError(S);
+}
+
+bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
+  return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
+}
+
 ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
   if (getLexer().isNot(AsmToken::Identifier))
     return ParseStatus::NoMatch;
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index a5e76668db6b9..4363e5c5176c9 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -344,6 +344,39 @@ static DecodeStatus DecodeVMV0RegisterClass(MCInst &Inst, uint32_t RegNo,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeTRRegisterClass(MCInst &Inst, uint32_t RegNo,
+                                          uint64_t Address,
+                                          const MCDisassembler *Decoder) {
+  if (RegNo > 15)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM2RegisterClass(MCInst &Inst, uint32_t RegNo,
+                                            uint64_t Address,
+                                            const MCDisassembler *Decoder) {
+  if (RegNo > 15 || RegNo % 2)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM4RegisterClass(MCInst &Inst, uint32_t RegNo,
+                                            uint64_t Address,
+                                            const MCDisassembler *Decoder) {
+  if (RegNo > 15 || RegNo % 4)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeVMaskReg(MCInst &Inst, uint32_t RegNo,
                                    uint64_t Address,
                                    const MCDisassembler *Decoder) {
@@ -722,9 +755,9 @@ static constexpr FeatureBitset XqciFeatureGroup = {
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
-    RISCV::FeatureVendorXSfvcp, RISCV::FeatureVendorXSfvqmaccdod,
-    RISCV::FeatureVendorXSfvqmaccqoq, RISCV::FeatureVendorXSfvfwmaccqqq,
-    RISCV::FeatureVendorXSfvfnrclipxfqf};
+    RISCV::FeatureVendorXSfvcp,          RISCV::FeatureVendorXSfvqmaccdod,
+    RISCV::FeatureVendorXSfvqmaccqoq,    RISCV::FeatureVendorXSfvfwmaccqqq,
+    RISCV::FeatureVendorXSfvfnrclipxfqf, RISCV::FeatureVendorXSfmmbase};
 static constexpr FeatureBitset XSfSystemGroup = {
     RISCV::FeatureVendorXSiFivecdiscarddlone,
     RISCV::FeatureVendorXSiFivecflushdlone,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index dc6937bb74a3c..1f4a77414db6b 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -227,6 +227,20 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
   RISCVVType::printVType(Imm, O);
 }
 
+void RISCVInstPrinter::printXSfmmVType(const MCInst *MI, unsigned OpNo,
+                                       const MCSubtargetInfo &STI,
+                                       raw_ostream &O) {
+  unsigned Imm = MI->getOperand(OpNo).getImm();
+  assert(RISCVVType::isValidXSfmmVType(Imm));
+  unsigned SEW = RISCVVType::getSEW(Imm);
+  O << "e" << SEW;
+  bool AltFmt = RISCVVType::isAltFmt(Imm);
+  if (AltFmt)
+    O << "alt";
+  unsigned Widen = RISCVVType::getXSfmmWiden(Imm);
+  O << ", w" << Widen;
+}
+
 // Print a Zcmp RList. If we are printing architectural register names rather
 // than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all
 // registers. Otherwise, we print "{ra, s0-s11}".
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
index 8a6129926d4f2..f8b8fd34abbb4 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -48,6 +48,8 @@ class RISCVInstPrinter : public MCInstPrinter {
                             const MCSubtargetInfo &STI, raw_ostream &O);
   void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
                    raw_ostream &O);
+  void printXSfmmVType(const MCInst *MI, unsigned OpNo,
+                       const MCSubtargetInfo &STI, raw_ostream &O);
   void printVMaskReg(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 b36d496137400..28b108c21f385 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1205,6 +1205,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
+
 def FeatureVendorXSfvqmaccdod
     : RISCVExtension<1, 0,
                      "SiFive Int8 Matrix Multiplication Instructions (2-by-8 and 8-by-2)",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 41b3a57315b57..8d76f0f476f23 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2267,6 +2267,7 @@ include "RISCVInstrInfoSFB.td"
 include "RISCVInstrInfoXVentana.td"
 include "RISCVInstrInfoXTHead.td"
 include "RISCVInstrInfoXSf.td"
+include "RISCVInstrInfoXSfmm.td"
 include "RISCVInstrInfoXCV.td"
 include "RISCVInstrInfoXwch.td"
 include "RISCVInstrInfoXqci.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td
new file mode 100644
index 0000000000000..66cb2d53da960
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td
@@ -0,0 +1,274 @@
+//===-- RISCVInstrInfoXsfmm.td - SiFive matrix multiply ----*- tablegen -*-===//
+//
+// 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 Xsfmm* vendor extensions defined by SiFive.
+//
+//===----------------------------------------------------------------------===//
+
+def XSfmmVTypeAsmOperand : AsmOperandClass {
+  let Name = "XSfmmVType";
+  let ParserMethod = "parseXSfmmVType";
+  let DiagnosticType = "InvalidXSfmmVType";
+  let RenderMethod = "addVTypeIOperands";
+}
+
+def XSfmmVTypeOp : RISCVOp {
+  let ParserMatchClass = XSfmmVTypeAsmOperand;
+  let PrintMethod = "printXSfmmVType";
+  let OperandType = "OPERAND_XSFMM_VTYPE";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    if (!isUInt<32>(Imm))
+      return false;
+    return RISCVVType::isValidXSfmmVType(Imm);
+  }];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class SFInstSetSingle<dag outs, dag ins, bits<5> rs2, string opcodestr,
+                      string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
+  bits<5> rs1;
+  bits<5> rd;
+
+  let Inst{31-25} = 0b1000010;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPCFG.Value;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Defs = [VTYPE, VL];
+}
+
+class SFInstTileMemOp<dag outs, dag ins, bits<3> nf, RISCVOpcode opcode,
+                      string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+
+  let Inst{31-29} = nf;
+  let Inst{28} = 1;
+  let Inst{27-26} = MOPLDUnitStride.Value;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = 0b111;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = opcode.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class SFInstTileLoad<bits<3> nf, string opcodestr>
+    : SFInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_LOAD_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class SFInstTileStore<bits<3> nf, string opcodestr>
+    : SFInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_STORE_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class SFInstTileMoveOp<bits<6> funct6, dag outs, dag ins, string opcodestr,
+                       string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+  bits<5> vd;
+
+  let Inst{31-26} = funct6;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = vd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class SFInstMatmulF<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b111100;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-9} = rd{3-1};
+  let Inst{8-7} = 0b00;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class SFInstMatmulF8<bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-27} = 0b11111;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+
+class F8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar F8Encodes = [F8Encode<0b0, "e5m2">,
+                    F8Encode<0b1, "e4m3">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class SFInstMatmulI8<bit funct6_1, bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-28} = 0b1111;
+  let Inst{27} = funct6_1;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPIVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+class I8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar I8Encodes = [I8Encode<0, "u">,
+                    I8Encode<1, "s">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class SFInstSetZero<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11110;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-8} = rd;
+  let Inst{7} = 0;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class SFInstVtDiscard<string opcodestr>
+    : RVInst<(outs), (ins), opcodestr, "", [], InstFormatR> {
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11100;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+let Predicates = [HasVendorXSfmmbase] in
+def : InstAlias<"sf.vsettnt $rd, $rs1, $vtypei",
+                (VSETVLI GPR:$rd, GPR:$rs1, XSfmmVTypeOp:$vtypei)>;
+
+let DecoderNamespace = "XSfvector" in {
+
+let Predicates = [HasVendorXSfmmbase] in {
+  def SF_VSETTN : SFInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00000,
+                                  "sf.vsettn", "$rd, $rs1">;
+  def SF_VSETTM : SFInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00001,
+                                  "sf.vsettm", "$rd, $rs1">;
+  def SF_VSETTK : SFInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00010,
+                                   "sf.vsettk", "$rd, $rs1">;
+  def SF_VTDISCARD : SFInstVtDiscard<"sf.vtdiscard">;
+
+  def SF_VTMV_V_T : SFInstTileMoveOp<0b010000, (outs VR:$vd), (ins GPR:$rs1),
+                                     "sf.vtmv.v.t", "$vd, $rs1"> {
+    let rs2 = 0b11111;
+  }
+  def SF_VTMV_T_V : SFInstTileMoveOp<0b010111, (outs), (ins GPR:$rs1, VR:$rs2),
+                                     "sf.vtmv.t.v", "$rs1, $rs2"> {
+    let vd = 0b00000;
+  }
+
+  def SF_VTZERO_T : SFInstSetZero<(outs), (ins TR:$rd), "sf.vtzero.t", "$rd">;
+
+  def SF_VLTE8  : SFInstTileLoad<0b000, "sf.vlte8">;
+  def SF_VLTE16 : SFInstTileLoad<0b001, "sf.vlte16">;
+  def SF_VLTE32 : SFInstTileLoad<0b010, "sf.vlte32">;
+  def SF_VLTE64 : SFInstTileLoad<0b011, "sf.vlte64">;
+
+  def SF_VSTE8  : SFInstTileStore<0b000, "sf.vste8">;
+  def SF_VSTE16 : SFInstTileStore<0b001, "sf.vste16">;
+  def SF_VSTE32 : SFInstTileStore<0b010, "sf.vste32">;
+  def SF_VSTE64 : SFInstTileStore<0b011, "sf.vste64">;
+} // Predicates = [HasVendorXSfmmbase]
+
+let Predicates = [HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f] in {
+  let Uses = [FRM], mayRaiseFPException = true in
+  def SF_MM_F_F   : SFInstMatmulF<(outs), (ins TRM2:$rd, VR:$vs2, VR:$vs1),
+                                  "sf.mm.f.f", "$rd, $vs2, $vs1">;
+} // Predicates = [HasVendorXSfmm32a16fOrXSfmm64a32fOrXSfmm64a64f]
+
+let Predicates = [HasVendorXSfmm32a8i] in {
+  foreach a = I8Encodes in
+    foreach b = I8Encodes in
+      def SF_MM_#!toupper(a.Name)#_#!toupper(b.Name)
+          : SFInstMatmulI8<0, a.Encoding, b.Encoding,
+                           (outs), (ins TRM4:$rd, VR:$vs2, VR:$vs1),
+                           "sf.mm."#a.Name#"."#b.Name, "$rd, $vs2, $vs1">;
+} // Predicates = [HasVendorXSfmm32a8i]
+
+let Predicates = [HasVendorXSfmm32a8f] in {
+let Uses = [FRM], mayRaiseFPException = true in {
+  foreach a = F8Encodes in
+    foreach b = F8Encodes in
+      def SF_MM_#!toupper(a.Name)#_#!toupper(b.Name)
+          : SFInstMatmulF8<a.Encoding, b.Encoding,
+                           (outs), (ins TRM4:$rd, VR:$vs2, VR:$vs1),
+                           "sf.mm."#a.Name#"."#b.Name, "$rd, $vs2, $vs1">;
+}
+} // Predicates = [HasVendorXSfmm32a8f]
+
+} // DecoderNamespace = "XSfvector"
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index cd725ca6166e2..80213e1503b0a 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -856,3 +856,16 @@ def : RISCVRegisterClass<[XLenVT], 32, (add SF_VCIX_STATE)> {
   let RegInfos = XLenRI;
   let isAllocatable = 0;
 }
+
+//===----------------------------------------------------------------------===//
+// XSfmmbase tiles
+//===----------------------------------------------------------------------===//
+foreach Index = 0-15 in
+  def T#Index : RISCVReg<Index, "mt"#Index, []>,
+                DwarfRegNum<[!add(Index, 3072)]>;
+
+let RegInfos = XLenRI in {
+  def TR   : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>;
+  def TRM2 : RISCVRegisterClass<[untyped], 32, (add (decimate TR, 2))>;
+  def TRM4 : RISCVRegisterClass<[untyped], 32, (add (decimate TR, 4))>;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 035ce4745cfd9..0eef7b1feaf5b 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -99,6 +99,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool ATTRIBUTE = DEFAULT;
 #include "RISCVGenSubtargetInfo.inc"
 
+  unsigned XSfmmTE = 0;
   unsigned ZvlLen = 0;
   unsigned RVVVectorBitsMin;
   unsigned RVVVectorBitsMax;
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 5bd7de1d3ca46..2e5e8f4e50c9c 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -164,6 +164,15 @@ unsigned encodeVTYPE(VLMUL VLMul, unsigned SEW, bool TailAgnostic,
   return VTypeI;
 }
 
+unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt) {
+  assert(isValidSEW(SEW) && "Invalid SEW");
+  assert((Widen == 1 || Widen == 2 || Widen == 4) && "Invalid Widen");
+  unsigned VSEWBits = encodeSEW(SEW);
+  unsigned TWiden = Log2_32(Widen) + 1;
+  unsigned VTypeI = (VSEWBits << 3) | AltFmt << 8 | TWiden << 9;
+  return VTypeI;
+}
+
 std::pair<unsigned, bool> decodeVLMUL(VLMUL VLMul) {
   switch (VLMul) {
   default:
diff --git a/llvm/test/CodeGen/RISCV/attributes-sifive.ll b/llvm/test/CodeGen/RISCV/attributes-sifive.ll
new file mode 100644
index 0000000000000..7afb939d1cf87
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/attributes-sifive.ll
@@ -0,0 +1,50 @@
+;; Generate ELF attributes from llc.
+
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm128t %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM128T %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm16t %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM16T %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm32a8i %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM32A8I %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm32a8f %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM32A8F %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm32a16f %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM32A16F %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm32a32f %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM32A32F %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm32t %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM32T %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm64a64f %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM64A64F %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmm64t %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMM64T %s
+; RUN: llc -mtriple=riscv32 -mattr=+xsfmmbase %s -o - | FileCheck --check-prefixes=CHECK,RV32XSFMMBASE %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm128t %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM128T %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm16t %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM16T %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm32a8i %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM32A8I %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm32a8f %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM32A8F %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm32a16f %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM32A16F %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm32a32f %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM32A32F %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm32t %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM32T %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm64a64f %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM64A64F %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmm64t %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMM64T %s
+; RUN: llc -mtriple=riscv64 -mattr=+xsfmmbase %s -o - | FileCheck --check-prefixes=CHECK,RV64XSFMMBASE %s
+
+; CHECK: .attribute 4, 16
+
+; RV32XSFMM128T: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0_xsfmm128t0p6_xsfmmbase0p6"
+; RV32XSFMM16T: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_zvl64b1p0_xsfmm16t0p6_xsfmmbase0p6" 
+; RV32XSFMM32A8I: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmm32a8i0p6_xsfmmbase0p6"
+; RV32XSFMM32A8F: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a8f0p6_xsfmmbase0p6"
+; RV32XSFMM32A16F: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a16f0p6_xsfmmbase0p6"
+; RV32XSFMM32A32F: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a32f0p6_xsfmmbase0p6"
+; RV32XSFMM32T: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xsfmm32t0p6_xsfmmbase0p6"
+; RV32XSFMM64A64F: .attribute 5, "rv32i2p1_f2p2_d2p2_zicsr2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl32b1p0_zvl64b1p0_xsfmm64a64f0p6_xsfmmbase0p6"
+; RV32XSFMM64T: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0_xsfmm64t0p6_xsfmmbase0p6"
+; RV32XSFMMBASE: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmmbase0p6"
+; RV64XSFMM128T: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0_xsfmm128t0p6_xsfmmbase0p6"
+; RV64XSFMM16T: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_zvl64b1p0_xsfmm16t0p6_xsfmmbase0p6"
+; RV64XSFMM32A8I: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmm32a8i0p6_xsfmmbase0p6"
+; RV64XSFMM32A8F: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a8f0p6_xsfmmbase0p6"
+; RV64XSFMM32A16F: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a16f0p6_xsfmmbase0p6"
+; RV64XSFMM32A32F: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a32f0p6_xsfmmbase0p6"
+; RV64XSFMM32T: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xsfmm32t0p6_xsfmmbase0p6"
+; RV64XSFMM64A64F: .attribute 5, "rv64i2p1_f2p2_d2p2_zicsr2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl32b1p0_zvl64b1p0_xsfmm64a64f0p6_xsfmmbase0p6"
+; RV64XSFMM64T: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0_xsfmm64t0p6_xsfmmbase0p6"
+; RV64XSFMMBASE: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmmbase0p6"
+
+define i32 @addi(i32 %a) {
+  %1 = add i32 %a, 1
+  ret i32 %1
+}
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 00311bab50836..6c2b8af55acce 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -184,6 +184,16 @@
 ; CHECK-NEXT:   xmipscmov                        - 'XMIPSCMov' (MIPS conditional move instruction (mips.ccmov)).
 ; CHECK-NEXT:   xmipslsp                         - 'XMIPSLSP' (MIPS optimization for hardware load-store bonding).
 ; CHECK-NEXT:   xsfcease                         - 'XSfcease' (SiFive sf.cease Instruction).
+; CHECK-NEXT:   xsfmm128t                        - 'XSfmm128t' (TE=128 configuration).
+; CHECK-NEXT:   xsfmm16t                         - 'XSfmm16t' (TE=16 configuration).
+; CHECK-NEXT:   xsfmm32a16f                      - 'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)). 
+; CHECK-NEXT:   xsfmm32a32f                      - 'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b). 
+; CHECK-NEXT:   xsfmm32a8f                       - 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8). 
+; CHECK-NEXT:   xsfmm32a8i                       - 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b). 
+; CHECK-NEXT:   xsfmm32t                         - 'XSfmm32t' (TE=32 configuration). 
+; CHECK-NEXT:   xsfmm64a64f                      - 'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64). 
+; CHECK-NEXT:   xsfmm64t                         - 'XSfmm64t' (TE=64 configuration). 
+; CHECK-NEXT:   xsfmmbase                        - 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero).
 ; CHECK-NEXT:   xsfvcp                           - 'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions).
 ; CHECK-NEXT:   xsfvfnrclipxfqf                  - 'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions).
 ; CHECK-NEXT:   xsfvfwmaccqqq                    - 'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4)).
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
index fc3bb13df77d6..f151569ef4e57 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
+++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
@@ -24,7 +24,7 @@ body:             |
     ; CHECK-NEXT: renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, [[COPY1]], 1, 6 /* e64 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 8)
     ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 8, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
     ; CHECK-NEXT: renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, [[COPY]], 8, 5 /* e32 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 4)
-    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3997705 /* reguse:VR */, killed renamable $v10, 3997705 /* reguse:VR */, killed renamable $v11, 3997705 /* reguse:VR */, killed renamable $v8, 3997705 /* reguse:VR */, killed renamable $v9
+    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 4194313 /* reguse:VR */, killed renamable $v10, 4194313 /* reguse:VR */, killed renamable $v11, 4194313 /* reguse:VR */, killed renamable $v8, 4194313 /* reguse:VR */, killed renamable $v9
     ; CHECK-NEXT: PseudoRET
     %3:gpr = COPY $x12
     %2:gpr = COPY $x11
@@ -34,7 +34,7 @@ body:             |
     renamable $v11 = PseudoVMV_S_X undef renamable $v11, %1, 8, 5 /* e32 */
     renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, %2, 1, 6 /* e64 */, 2 /* tu, ma */ :: (load unknown-size, align 8)
     renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, %3, 8, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size, align 4)
-    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3997705 /* reguse:VR */, killed renamable $v10, 3997705 /* reguse:VR */, killed renamable $v11, 3997705 /* reguse:VR */, killed renamable $v8, 3997705 /* reguse:VR */, killed renamable $v9
+    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 4194313 /* reguse:VR */, killed renamable $v10, 4194313 /* reguse:VR */, killed renamable $v11, 4194313 /* reguse:VR */, killed renamable $v8, 4194313 /* reguse:VR */, killed renamable $v9
     PseudoRET
 
 ...
diff --git a/llvm/test/MC/RISCV/attribute-arch-sifive.s b/llvm/test/MC/RISCV/attribute-arch-sifive.s
new file mode 100644
index 0000000000000..45eeb722b8d95
--- /dev/null
+++ b/llvm/test/MC/RISCV/attribute-arch-sifive.s
@@ -0,0 +1,34 @@
+## Arch string without version.
+
+# RUN: llvm-mc %s -triple=riscv32 -filetype=asm | FileCheck %s
+# RUN: llvm-mc %s -triple=riscv64 -filetype=asm | FileCheck %s
+
+.attribute arch, "rv32i_xsfmm128t"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0_xsfmm128t0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm16t"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_zvl64b1p0_xsfmm16t0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm32a8i"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmm32a8i0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm32a8f"
+# CHECK: attribute      5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a8f0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm32a16f"
+# CHECK: attribute      5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a16f0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm32a32f"
+# CHECK: attribute      5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfmm32a32f0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm32t"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xsfmm32t0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm64a64f"
+# CHECK: attribute      5, "rv32i2p1_f2p2_d2p2_zicsr2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl32b1p0_zvl64b1p0_xsfmm64a64f0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmm64t"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0_xsfmm64t0p6_xsfmmbase0p6"
+
+.attribute arch, "rv32i_xsfmmbase"
+# CHECK: attribute      5, "rv32i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfmmbase0p6"
diff --git a/llvm/test/MC/RISCV/rvv/xsfmm-invalid.s b/llvm/test/MC/RISCV/rvv/xsfmm-invalid.s
new file mode 100644
index 0000000000000..6b17d25b4b903
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/xsfmm-invalid.s
@@ -0,0 +1,30 @@
+# RUN: not llvm-mc -triple=riscv32 --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8f,+xsfmm64a64f %s 2>&1 \
+# RUN:        | FileCheck %s --check-prefix=CHECK
+# RUN: not llvm-mc -triple=riscv64 --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8f,+xsfmm64a64f %s 2>&1 \
+# RUN:        | FileCheck %s --check-prefix=CHECK
+
+sf.vsettnt a0, a1, e128, w1 # CHECK: :[[@LINE]]:20: error: operand must be e[8|16|16alt|32|64],w[1|2|4]
+
+sf.vsettnt a0, a1, e8alt, w1 # CHECK: :[[@LINE]]:20: error: operand must be e[8|16|16alt|32|64],w[1|2|4]
+
+sf.vsettnt a0, a1, e16alt, w1, a2 # CHECK: :[[@LINE]]:20: error: operand must be e[8|16|16alt|32|64],w[1|2|4]
+
+sf.mm.f.f mt1, v8, v9 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+
+sf.mm.e5m2.e5m2 mt2, v8, v9 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction
+
+sf.mm.e5m2.e4m3 mt6, v8, v9 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction
+
+sf.mm.e4m3.e5m2 mt10, v8, v9 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction
+
+sf.mm.e4m3.e4m3 mt14, v8, v9 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction
+
+sf.mm.u.u mt1, v8, v9 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+
+sf.mm.s.u mt2, v8, v9 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+
+sf.mm.u.s mt3, v8, v9 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+
+sf.mm.s.s mt1, v8, v9 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rvv/xsfmm.s b/llvm/test/MC/RISCV/rvv/xsfmm.s
new file mode 100644
index 0000000000000..8de520aa964b7
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/xsfmm.s
@@ -0,0 +1,200 @@
+# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: not llvm-mc -triple=riscv32 -show-encoding %s 2>&1 \
+# RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \
+# RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+# RUN: llvm-mc -triple=riscv32 -filetype=obj --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | llvm-objdump -d  --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f --no-print-imm-hex - \
+# RUN:        | FileCheck %s --check-prefix=CHECK-INST
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | llvm-objdump -d  --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f --no-print-imm-hex - \
+# RUN:        | FileCheck %s --check-prefix=CHECK-INST
+# RUN: llvm-mc -triple=riscv32 -filetype=obj --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+xsfmmbase, \
+# RUN:     --mattr=+xsfmm32a32f,+xsfmm32a8i,+xsfmm32a8f,+xsfmm64a64f %s \
+# RUN:        | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+# CHECK-INST: sf.vsettnt a0, a1, e8, w1
+# CHECK-ENCODING: [0x57,0xf5,0x05,0x20]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 2005f557 <unknown>
+sf.vsettnt a0, a1, e8, w1
+
+# CHECK-INST: sf.vsettnt a0, a1, e16alt, w1
+# CHECK-ENCODING: [0x57,0xf5,0x85,0x30]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 3085f557 <unknown>
+sf.vsettnt a0, a1, e16alt, w1
+
+# CHECK-INST: sf.vsettnt a0, a1, e8, w1
+# CHECK-ENCODING: [0x57,0xf5,0x05,0x20]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Extension for Application Processors), 'Zve32x' (Vector Extensions for Embedded Processors)
+# CHECK-UNKNOWN: 2005f557 <unknown>
+vsetvli a0, a1, 0x200
+
+# CHECK-INST: sf.vsettnt a0, a1, e16alt, w1
+# CHECK-ENCODING: [0x57,0xf5,0x85,0x30]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Extension for Application Processors), 'Zve32x' (Vector Extensions for Embedded Processors)
+# CHECK-UNKNOWN: 3085f557 <unknown>
+vsetvli a0, a1, 0x308
+
+# CHECK-INST: sf.vsettn a0, a1
+# CHECK-ENCODING: [0x57,0xf5,0x05,0x84]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 8405f557 <unknown>
+sf.vsettn a0, a1
+
+# CHECK-INST: sf.vsettm a0, a1
+# CHECK-ENCODING: [0x57,0xf5,0x15,0x84]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 8415f557 <unknown>
+sf.vsettm a0, a1
+
+# CHECK-INST: sf.vsettk a0, a1
+# CHECK-ENCODING: [0x57,0xf5,0x25,0x84]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 8425f557 <unknown>
+sf.vsettk a0, a1
+
+# CHECK-INST: sf.vlte8  a0, (a1)
+# CHECK-ENCODING: [0x07,0xf0,0xa5,0x12]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 12a5f007 <unknown>
+sf.vlte8  a0, (a1)
+
+# CHECK-INST: sf.vlte16 a0, (a1)
+# CHECK-ENCODING: [0x07,0xf0,0xa5,0x32]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 32a5f007 <unknown>
+sf.vlte16 a0, (a1)
+
+# CHECK-INST: sf.vlte32 a0, (a1)
+# CHECK-ENCODING: [0x07,0xf0,0xa5,0x52]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 52a5f007 <unknown>
+sf.vlte32 a0, (a1)
+
+# CHECK-INST: sf.vlte64 a0, (a1)
+# CHECK-ENCODING: [0x07,0xf0,0xa5,0x72]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 72a5f007 <unknown>
+sf.vlte64 a0, (a1)
+
+# CHECK-INST: sf.vste8  a0, (a1)
+# CHECK-ENCODING: [0x27,0xf0,0xa5,0x12]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 12a5f027 <unknown>
+sf.vste8  a0, (a1)
+
+# CHECK-INST: sf.vste16 a0, (a1)
+# CHECK-ENCODING: [0x27,0xf0,0xa5,0x32]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 32a5f027 <unknown>
+sf.vste16 a0, (a1)
+
+# CHECK-INST: sf.vste32 a0, (a1)
+# CHECK-ENCODING: [0x27,0xf0,0xa5,0x52]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 52a5f027 <unknown>
+sf.vste32 a0, (a1)
+
+# CHECK-INST: sf.vste64 a0, (a1)
+# CHECK-ENCODING: [0x27,0xf0,0xa5,0x72]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 72a5f027 <unknown>
+sf.vste64 a0, (a1)
+
+# CHECK-INST: sf.vtmv.v.t v8, a0
+# CHECK-ENCODING: [0x57,0x64,0xf5,0x43]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 43f56457 <unknown>
+sf.vtmv.v.t v8, a0
+
+# CHECK-INST: sf.vtmv.t.v a0, v8
+# CHECK-ENCODING: [0x57,0x60,0x85,0x5e]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 5e856057 <unknown>
+sf.vtmv.t.v a0, v8
+
+# CHECK-INST: sf.mm.f.f mt2, v8, v9
+# CHECK-ENCODING: [0x77,0x92,0x84,0xf2]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or 'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or 'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64){{$}}
+# CHECK-UNKNOWN: f2849277 <unknown>
+sf.mm.f.f mt2, v8, v9
+
+# CHECK-INST: sf.mm.e5m2.e5m2 mt0, v8, v9
+# CHECK-ENCODING: [0x77,0x90,0x84,0xfa]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8){{$}}
+# CHECK-UNKNOWN: fa849077 <unknown>
+sf.mm.e5m2.e5m2 mt0, v8, v9
+
+# CHECK-INST: sf.mm.e5m2.e4m3 mt4, v8, v9
+# CHECK-ENCODING: [0xf7,0x94,0x84,0xfa]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8){{$}}
+# CHECK-UNKNOWN: fa8494f7 <unknown>
+sf.mm.e5m2.e4m3 mt4, v8, v9
+
+# CHECK-INST: sf.mm.e4m3.e5m2 mt8, v8, v9
+# CHECK-ENCODING: [0x77,0x98,0x84,0xfe]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8){{$}}
+# CHECK-UNKNOWN: fe849877 <unknown>
+sf.mm.e4m3.e5m2 mt8, v8, v9
+
+# CHECK-INST: sf.mm.e4m3.e4m3 mt12, v8, v9
+# CHECK-ENCODING: [0xf7,0x9c,0x84,0xfe]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8){{$}}
+# CHECK-UNKNOWN: fe849cf7 <unknown>
+sf.mm.e4m3.e4m3 mt12, v8, v9
+
+# CHECK-INST: sf.mm.u.u mt0, v8, v9
+# CHECK-ENCODING: [0x77,0x80,0x84,0xf2]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b){{$}}
+# CHECK-UNKNOWN: f2848077 <unknown>
+sf.mm.u.u mt0, v8, v9
+
+# CHECK-INST: sf.mm.s.u mt4, v8, v9
+# CHECK-ENCODING: [0x77,0x84,0x84,0xf6]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b){{$}}
+# CHECK-UNKNOWN: f6848477 <unknown>
+sf.mm.s.u mt4, v8, v9
+
+# CHECK-INST: sf.mm.u.s mt8, v8, v9
+# CHECK-ENCODING: [0xf7,0x88,0x84,0xf2]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b){{$}}
+# CHECK-UNKNOWN: f28488f7 <unknown>
+sf.mm.u.s mt8, v8, v9
+
+# CHECK-INST: sf.mm.s.s mt12, v8, v9
+# CHECK-ENCODING: [0xf7,0x8c,0x84,0xf6]
+# CHECK-ERROR: instruction requires the following: 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b){{$}}
+# CHECK-UNKNOWN: f6848cf7 <unknown>
+sf.mm.s.s mt12, v8, v9
+
+# CHECK-INST: sf.vtzero.t mt15
+# CHECK-ENCODING: [0x57,0x6f,0xe0,0x43]
+# CHECK-ERROR: instruction requires the following: 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero){{$}}
+# CHECK-UNKNOWN: 43e06f57 <unknown>
+sf.vtzero.t mt15
+
+# CHECK-INST: vsetvl a2, a0, a1
+# CHECK-ENCODING: [0x57,0x76,0xb5,0x80]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Extension for Application Processors), 'Zve32x' (Vector Extensions for Embedded Processors)
+# CHECK-UNKNOWN: 80b57657 <unknown>
+vsetvl a2, a0, a1
+
+# CHECK-INST:  vsetvli a0, a1, e8, m1, tu, mu
+# CHECK-ENCODING: [0x57,0xf5,0x05,0x00]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Extension for Application Processors), 'Zve32x' (Vector Extensions for Embedded Processors)
+# CHECK-UNKNOWN: 0005f557 <unknown>
+vsetvli a0, a1, e8, m1, tu, mu
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index fc6854a483f6f..7a2539e80388c 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1141,6 +1141,16 @@ R"(All available -march extensions for RISC-V
     xmipscmov            1.0
     xmipslsp             1.0
     xsfcease             1.0
+    xsfmm128t            0.6
+    xsfmm16t             0.6
+    xsfmm32a16f          0.6
+    xsfmm32a32f          0.6
+    xsfmm32a8f           0.6
+    xsfmm32a8i           0.6
+    xsfmm32t             0.6
+    xsfmm64a64f          0.6
+    xsfmm64t             0.6
+    xsfmmbase            0.6
     xsfvcp               1.0
     xsfvfnrclipxfqf      1.0
     xsfvfwmaccqqq        1.0


Reviews:
user: login: wangpc-pp
body: I have followed the progress of IME/AME for a long time, there are several candidates in parallel. I think the support of these extensions should be marked as early access, and we can review these patches but won't merge them until they are ratified just like Zvzip/Zvabd/Zibimm/...
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T03:32:52Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T03:34:36Z
user: login: MaskRay
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-27T03:36:43Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T03:38:03Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T03:40:41Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T03:42:45Z
user: login: wangpc-pp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T08:03:19Z
user: login: preames
body: First pass of technical comments.  I need to take a much more careful look at e.g. encodings, but will do that on the next round.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-17T18:09:32Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-17T19:51:56Z
user: login: sequencer
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-30T02:29:42Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-30T05:12:35Z
user: login: sequencer
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-30T05:30:04Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-30T06:16:31Z
user: login: sequencer
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-30T06:18:24Z
user: login: wangpc-pp
body: LGTM.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T03:23:05Z
user: login: MaskRay
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-20T16:19:18Z
user: login: topperc
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T17:06:52Z

Review comments:
diff_hunk: @@ -24,7 +24,7 @@ body:             |
     ; CHECK-NEXT: renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, [[COPY1]], 1, 6 /* e64 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 8)
     ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 8, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
     ; CHECK-NEXT: renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, [[COPY]], 8, 5 /* e32 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 4)
-    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3145737 /* reguse:VR */, killed renamable $v10, 3145737 /* reguse:VR */, killed renamable $v11, 3145737 /* reguse:VR */, killed renamable $v8, 3145737 /* reguse:VR */, killed renamable $v9
+    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3342345 /* reguse:VR */, killed renamable $v10, 3342345 /* reguse:VR */, killed renamable $v11, 3342345 /* reguse:VR */, killed renamable $v8, 3342345 /* reguse:VR */, killed renamable $v9
path: llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
user: login: wangpc-pp
body: What's the meaning of 3342345 and why is it changed?
created_at: 2025-03-27T03:29:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -830,3 +830,16 @@ def : RISCVRegisterClass<[XLenVT], 32, (add SF_VCIX_STATE)> {
   let RegInfos = XLenRI;
   let isAllocatable = 0;
 }
+
+//===----------------------------------------------------------------------===//
+// XSfmmbase tiles
+//===----------------------------------------------------------------------===//
+foreach Index = 0-15 in
+  def T#Index : RISCVReg<Index, "mt"#Index, []>,
+                DwarfRegNum<[!add(Index, 3072)]>;
+
+let RegInfos = XLenRI in {
+  def TR   : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>;
path: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
user: login: wangpc-pp
body: I have a PoC to use Target Extension Type to support matrix, does SiFive try this machanism in the CodeGen?
created_at: 2025-03-27T03:31:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,7 +24,7 @@ body:             |
     ; CHECK-NEXT: renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, [[COPY1]], 1, 6 /* e64 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 8)
     ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 8, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
     ; CHECK-NEXT: renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, [[COPY]], 8, 5 /* e32 */, 2 /* tu, ma */, implicit $vl, implicit $vtype :: (load unknown-size, align 4)
-    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3145737 /* reguse:VR */, killed renamable $v10, 3145737 /* reguse:VR */, killed renamable $v11, 3145737 /* reguse:VR */, killed renamable $v8, 3145737 /* reguse:VR */, killed renamable $v9
+    ; CHECK-NEXT: INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3342345 /* reguse:VR */, killed renamable $v10, 3342345 /* reguse:VR */, killed renamable $v11, 3342345 /* reguse:VR */, killed renamable $v8, 3342345 /* reguse:VR */, killed renamable $v9
path: llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
user: login: topperc
body: The upper 16 bits are the LLVM internal numbering for the VR register class. Adding TR changed the internal numbering.
created_at: 2025-03-27T03:34:35Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,95 @@
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm128t -x c -E -dM %s \
path: clang/test/Preprocessor/riscv-target-features-sifive.c
user: login: MaskRay
body: indent continuation lines by 2 spaces.

Remove unneeded `-x c`
created_at: 2025-03-27T03:36:43Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,95 @@
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm128t -x c -E -dM %s \
path: clang/test/Preprocessor/riscv-target-features-sifive.c
user: login: topperc
body: This pattern exists in many places in clang/test/Preprocessor/riscv-target-features.c. Should we fix those?
created_at: 2025-03-27T03:38:03Z
author_association: COLLABORATOR
diff_hunk: @@ -830,3 +830,16 @@ def : RISCVRegisterClass<[XLenVT], 32, (add SF_VCIX_STATE)> {
   let RegInfos = XLenRI;
   let isAllocatable = 0;
 }
+
+//===----------------------------------------------------------------------===//
+// XSfmmbase tiles
+//===----------------------------------------------------------------------===//
+foreach Index = 0-15 in
+  def T#Index : RISCVReg<Index, "mt"#Index, []>,
+                DwarfRegNum<[!add(Index, 3072)]>;
+
+let RegInfos = XLenRI in {
+  def TR   : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>;
path: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
user: login: topperc
body: We have done some experiment with that, but our current thought is to use constant "tile id" for intrinsics instead of allocating tiles in compiler. This what AArch64 SME does.

This ISA doesn't support load, store, or copy of whole tiles. These require loops to emulate using vector registers.

I think using Target Extension Type still needs an underlying type to calculate size. The tiles here are scalable in two dimensions which `TypeSize` can't represent.
created_at: 2025-03-27T03:40:40Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,95 @@
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm128t -x c -E -dM %s \
path: clang/test/Preprocessor/riscv-target-features-sifive.c
user: login: topperc
body: I guess many of them have been fixed already, but there are still a few left.
created_at: 2025-03-27T03:42:45Z
author_association: COLLABORATOR
diff_hunk: @@ -830,3 +830,16 @@ def : RISCVRegisterClass<[XLenVT], 32, (add SF_VCIX_STATE)> {
   let RegInfos = XLenRI;
   let isAllocatable = 0;
 }
+
+//===----------------------------------------------------------------------===//
+// XSfmmbase tiles
+//===----------------------------------------------------------------------===//
+foreach Index = 0-15 in
+  def T#Index : RISCVReg<Index, "mt"#Index, []>,
+                DwarfRegNum<[!add(Index, 3072)]>;
+
+let RegInfos = XLenRI in {
+  def TR   : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>;
path: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
user: login: wangpc-pp
body: > The tiles here are scalable in two dimensions which TypeSize can't represent.

Yeah, we encountered the same problem and this is why XuanTie's AME is designed as that two dimensions are related IIRC.
created_at: 2025-03-27T08:03:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2302,6 +2316,81 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+bool RISCVAsmParser::parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State,
+                                          unsigned &WW, unsigned &EE,
+                                          bool &AltFmt) {
+  if (getLexer().isNot(AsmToken::Identifier))
+    return true;
+
+  StringRef Identifier = getTok().getIdentifier();
+
+  switch (State) {
+  case WWEEState_SEW:
+    if (!Identifier.consume_front("e"))
+      break;
path: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
user: login: preames
body: Minor, but use return instead of break for readability.  
created_at: 2025-04-17T17:50:55Z
author_association: COLLABORATOR
diff_hunk: @@ -2302,6 +2316,81 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+bool RISCVAsmParser::parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State,
+                                          unsigned &WW, unsigned &EE,
+                                          bool &AltFmt) {
+  if (getLexer().isNot(AsmToken::Identifier))
+    return true;
+
+  StringRef Identifier = getTok().getIdentifier();
+
+  switch (State) {
+  case WWEEState_SEW:
+    if (!Identifier.consume_front("e"))
+      break;
+    if (Identifier.getAsInteger(10, EE)) {
+      if (Identifier != "16alt")
+        break;
+
+      AltFmt = true;
+      EE = 16;
+    }
+    if (!RISCVVType::isValidSEW(EE))
+      break;
+    State = WWEEState_Widen;
+    return false;
+  case WWEEState_Widen:
+    if (!Identifier.consume_front("w"))
+      break;
+    if (Identifier.getAsInteger(10, WW))
+      break;
+    if (WW != 1 && WW != 2 && WW != 4)
+      break;
+    State = WWEEState_Done;
+    return false;
+  case WWEEState_Done:
+    // Extra token?
+    break;
+  }
+
+  return true;
+}
+
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  unsigned Widen = 0;
+  unsigned SEW = 0;
+  bool AltFmt = false;
+
+  WWEEState State = WWEEState_SEW;
path: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
user: login: preames
body: It's not really clear to me that the state mechanism is worthwhile over just inlining the two calls and specializing the switch.  The state machine is exceedingly simple, and the extra helper may actually just confuse things.
created_at: 2025-04-17T17:53:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,276 @@
+//===-- RISCVInstrInfoXsfmm.td - SiFive matrix multiply ----*- tablegen -*-===//
+//
+// 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 Xsfmm* vendor extensions defined by SiFive.
+//
+//===----------------------------------------------------------------------===//
+
+def XSfmmVTypeAsmOperand : AsmOperandClass {
+  let Name = "XSfmmVType";
+  let ParserMethod = "parseXSfmmVType";
+  let DiagnosticType = "InvalidXSfmmVType";
+  let RenderMethod = "addVTypeIOperands";
+}
+
+def XSfmmVTypeOp : RISCVOp {
+  let ParserMatchClass = XSfmmVTypeAsmOperand;
+  let PrintMethod = "printXSfmmVType";
+  let OperandType = "OPERAND_XSFMM_VTYPE";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    if (!isUInt<32>(Imm))
+      return false;
+    return RISCVVType::isValidXSfmmVType(Imm);
+  }];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class RVInstSetSingle<dag outs, dag ins, bits<5> rs2, string opcodestr,
path: llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td
user: login: preames
body: All the classes should be prefixed with Sf
created_at: 2025-04-17T17:59:38Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,276 @@
+//===-- RISCVInstrInfoXsfmm.td - SiFive matrix multiply ----*- tablegen -*-===//
+//
+// 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 Xsfmm* vendor extensions defined by SiFive.
+//
+//===----------------------------------------------------------------------===//
+
+def XSfmmVTypeAsmOperand : AsmOperandClass {
+  let Name = "XSfmmVType";
+  let ParserMethod = "parseXSfmmVType";
+  let DiagnosticType = "InvalidXSfmmVType";
+  let RenderMethod = "addVTypeIOperands";
+}
+
+def XSfmmVTypeOp : RISCVOp {
+  let ParserMatchClass = XSfmmVTypeAsmOperand;
+  let PrintMethod = "printXSfmmVType";
+  let OperandType = "OPERAND_XSFMM_VTYPE";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    if (!isUInt<32>(Imm))
+      return false;
+    return RISCVVType::isValidXSfmmVType(Imm);
+  }];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class RVInstSetSingle<dag outs, dag ins, bits<5> rs2, string opcodestr,
+                      string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
+  bits<5> rs1;
+  bits<5> rd;
+
+  let Inst{31-25} = 0b1000010;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPCFG.Value;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Defs = [VTYPE, VL];
+}
+
+class RVInstTileMemOp<dag outs, dag ins, bits<3> nf, RISCVOpcode opcode,
+                      string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+
+  let Inst{31-29} = nf;
+  let Inst{28} = 1;
+  let Inst{27-26} = MOPLDUnitStride.Value;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = 0b111;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = opcode.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class RVInstTileLoad<bits<3> nf, string opcodestr>
+    : RVInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_LOAD_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class RVInstTileStore<bits<3> nf, string opcodestr>
+    : RVInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_STORE_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstTileMoveOp<bits<6> funct6, dag outs, dag ins, string opcodestr,
+                       string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+  bits<5> vd;
+
+  let Inst{31-26} = funct6;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = vd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulF<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b111100;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-9} = rd{3-1};
+  let Inst{8-7} = 0b00;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulF8<bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-27} = 0b11111;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+
+class F8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar F8Encodes = [F8Encode<0b0, "e5m2">,
+                    F8Encode<0b1, "e4m3">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulI8<bit funct6_1, bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-28} = 0b1111;
+  let Inst{27} = funct6_1;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPIVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+class I8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar I8Encodes = [I8Encode<0, "u">,
+                    I8Encode<1, "s">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstSetZero<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11110;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-8} = rd;
+  let Inst{7} = 0;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class RVInstVtDiscard<string opcodestr>
+    : RVInst<(outs), (ins), opcodestr, "", [], InstFormatR> {
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11100;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+let Predicates = [HasVendorXSfmmbase] in
+def : InstAlias<"sf.vsettnt $rd, $rs1, $vtypei",
+                (VSETVLI GPR:$rd, GPR:$rs1, XSfmmVTypeOp:$vtypei)>;
+
+let DecoderNamespace = "XSfmm" in {
path: llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td
user: login: preames
body: Can this be grouped into one of the existing decode tables?  Or does it need to be separate due the non-conforming nature?
created_at: 2025-04-17T18:02:53Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,276 @@
+//===-- RISCVInstrInfoXsfmm.td - SiFive matrix multiply ----*- tablegen -*-===//
+//
+// 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 Xsfmm* vendor extensions defined by SiFive.
+//
+//===----------------------------------------------------------------------===//
+
+def XSfmmVTypeAsmOperand : AsmOperandClass {
+  let Name = "XSfmmVType";
+  let ParserMethod = "parseXSfmmVType";
+  let DiagnosticType = "InvalidXSfmmVType";
+  let RenderMethod = "addVTypeIOperands";
+}
+
+def XSfmmVTypeOp : RISCVOp {
+  let ParserMatchClass = XSfmmVTypeAsmOperand;
+  let PrintMethod = "printXSfmmVType";
+  let OperandType = "OPERAND_XSFMM_VTYPE";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    if (!isUInt<32>(Imm))
+      return false;
+    return RISCVVType::isValidXSfmmVType(Imm);
+  }];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class RVInstSetSingle<dag outs, dag ins, bits<5> rs2, string opcodestr,
+                      string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
+  bits<5> rs1;
+  bits<5> rd;
+
+  let Inst{31-25} = 0b1000010;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPCFG.Value;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Defs = [VTYPE, VL];
+}
+
+class RVInstTileMemOp<dag outs, dag ins, bits<3> nf, RISCVOpcode opcode,
+                      string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+
+  let Inst{31-29} = nf;
+  let Inst{28} = 1;
+  let Inst{27-26} = MOPLDUnitStride.Value;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = 0b111;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = opcode.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class RVInstTileLoad<bits<3> nf, string opcodestr>
+    : RVInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_LOAD_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class RVInstTileStore<bits<3> nf, string opcodestr>
+    : RVInstTileMemOp<(outs), (ins GPR:$rs2, GPRMemZeroOffset:$rs1), nf,
+                      OPC_STORE_FP, opcodestr, "$rs2, ${rs1}">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstTileMoveOp<bits<6> funct6, dag outs, dag ins, string opcodestr,
+                       string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> rs2;
+  bits<5> rs1;
+  bits<5> vd;
+
+  let Inst{31-26} = funct6;
+  let Inst{25} = 1;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = vd;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulF<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b111100;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-9} = rd{3-1};
+  let Inst{8-7} = 0b00;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulF8<bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-27} = 0b11111;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPFVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+
+class F8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar F8Encodes = [F8Encode<0b0, "e5m2">,
+                    F8Encode<0b1, "e4m3">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstMatmulI8<bit funct6_1, bit a, bit b, dag outs, dag ins,
+                     string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-28} = 0b1111;
+  let Inst{27} = funct6_1;
+  let Inst{26} = a;
+  let Inst{25} = 1;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = vs1;
+  let Inst{14-12} = OPIVV.Value;
+  let Inst{11-10} = rd{3-2};
+  let Inst{9-8} = 0b00;
+  let Inst{7} = b;
+  let Inst{6-0} = OPC_OP_VE.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+class I8Encode<bit encoding, string name> {
+  bit Encoding = encoding;
+  string Name = name;
+}
+
+defvar I8Encodes = [I8Encode<0, "u">,
+                    I8Encode<1, "s">];
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVInstSetZero<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vs1;
+  bits<4> rd;
+
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11110;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-8} = rd;
+  let Inst{7} = 0;
+  let Inst{6-0} = OPC_OP_V.Value;
+
+  let Uses = [VTYPE, VL];
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class RVInstVtDiscard<string opcodestr>
+    : RVInst<(outs), (ins), opcodestr, "", [], InstFormatR> {
+  let Inst{31-26} = 0b010000;
+  let Inst{25} = 1;
+  let Inst{24-20} = 0b11100;
+  let Inst{19-15} = 0b00000;
+  let Inst{14-12} = OPMVX.Value;
+  let Inst{11-7} = 0b00000;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+let Predicates = [HasVendorXSfmmbase] in
+def : InstAlias<"sf.vsettnt $rd, $rs1, $vtypei",
+                (VSETVLI GPR:$rd, GPR:$rs1, XSfmmVTypeOp:$vtypei)>;
+
+let DecoderNamespace = "XSfmm" in {
+
+let Predicates = [HasVendorXSfmmbase] in {
+  def SF_VSETTN : RVInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00000,
+                                  "sf.vsettn", "$rd, $rs1">;
+  def SF_VSETTM : RVInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00001,
+                                  "sf.vsettm", "$rd, $rs1">;
+  def SF_VSETTK  : RVInstSetSingle<(outs GPR:$rd), (ins GPR:$rs1), 0b00010,
+                                   "sf.vsettk", "$rd, $rs1">;
+  def SF_VTDISCARD : RVInstVtDiscard<"sf.vtdiscard">;
+
+  def SF_VTMV_V_T : RVInstTileMoveOp<0b010000, (outs VR:$vd), (ins GPR:$rs1),
+                                     "sf.vtmv.v.t", "$vd, $rs1"> {
+    let rs2 = 0b11111;
+  }
+  def SF_VTMV_T_V : RVInstTileMoveOp<0b010111, (outs), (ins GPR:$rs1, VR:$rs2),
+                                     "sf.vtmv.t.v", "$rs1, $rs2"> {
+    let vd = 0b00000;
+  }
+
+  def SF_VTZERO_T : RVInstSetZero<(outs), (ins TR:$rd), "sf.vtzero.t", "$rd">;
+} // Predicates = [HasVendorXSfmmbase]
+
+let Predicates = [HasVendorXSfmmbase] in {
path: llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td
user: login: preames
body: Minor, merge with prior let.
created_at: 2025-04-17T18:03:44Z
author_association: COLLABORATOR
diff_hunk: @@ -34,7 +34,7 @@ body:             |
     renamable $v11 = PseudoVMV_S_X undef renamable $v11, %1, 8, 5 /* e32 */
     renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, %2, 1, 6 /* e64 */, 2 /* tu, ma */ :: (load unknown-size, align 8)
     renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, %3, 8, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size, align 4)
-    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3997705 /* reguse:VR */, killed renamable $v10, 3997705 /* reguse:VR */, killed renamable $v11, 3997705 /* reguse:VR */, killed renamable $v8, 3997705 /* reguse:VR */, killed renamable $v9
+    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 4194313 /* reguse:VR */, killed renamable $v10, 4194313 /* reguse:VR */, killed renamable $v11, 4194313 /* reguse:VR */, killed renamable $v8, 4194313 /* reguse:VR */, killed renamable $v9
path: llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
user: login: preames
body: Can you explain this change?
created_at: 2025-04-17T18:06:53Z
author_association: COLLABORATOR
diff_hunk: @@ -34,7 +34,7 @@ body:             |
     renamable $v11 = PseudoVMV_S_X undef renamable $v11, %1, 8, 5 /* e32 */
     renamable $v8 = PseudoVLE64_V_M1 undef renamable $v8, %2, 1, 6 /* e64 */, 2 /* tu, ma */ :: (load unknown-size, align 8)
     renamable $v9 = PseudoVLE32_V_M1 undef renamable $v9, %3, 8, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size, align 4)
-    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 3997705 /* reguse:VR */, killed renamable $v10, 3997705 /* reguse:VR */, killed renamable $v11, 3997705 /* reguse:VR */, killed renamable $v8, 3997705 /* reguse:VR */, killed renamable $v9
+    INLINEASM &"# use $0 $1 $2 $3", 1 /* sideeffect attdialect */, 4194313 /* reguse:VR */, killed renamable $v10, 4194313 /* reguse:VR */, killed renamable $v11, 4194313 /* reguse:VR */, killed renamable $v8, 4194313 /* reguse:VR */, killed renamable $v9
path: llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir
user: login: topperc
body: The upper 16 bits on these operands is the internal numbering for LLVM's register classes. Adding the tile register classes bumped the number. The test was also updated when GPRNoX31 register class was added in 536fe74aaac437e147fc64dada6af8aab79a8b54.
created_at: 2025-04-17T19:51:56Z
author_association: COLLABORATOR
diff_hunk: @@ -1197,6 +1197,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
path: llvm/lib/Target/RISCV/RISCVFeatures.td
user: login: sequencer
body: Based on the specification,
> `TE` is constrained to be a power of 2, `VLEN/4 >= TE >= 4`. The upper bound
is set by the requirement that a tile row or column must fit within a single vector register group (`VLEN*8` bits)

Since maximum size of VLEN is 64K, which means `TE` can be scale up to `64K/4=16K`, is possible for compiler to support this for a larger `TE`?
created_at: 2025-04-30T02:29:17Z
author_association: NONE
diff_hunk: @@ -1197,6 +1197,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
path: llvm/lib/Target/RISCV/RISCVFeatures.td
user: login: topperc
body: Are you asking me to add FeatureVendorXSfmm16384t?
created_at: 2025-04-30T05:12:35Z
author_association: COLLABORATOR
diff_hunk: @@ -1197,6 +1197,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
path: llvm/lib/Target/RISCV/RISCVFeatures.td
user: login: sequencer
body: Not so big TE, that’s not reasonable, however, VLEN=4K where TE=1K is a possible option in our case, so I may asking increase the maximum TE larger, e.g. 1K?
created_at: 2025-04-30T05:30:03Z
author_association: NONE
diff_hunk: @@ -1197,6 +1197,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
path: llvm/lib/Target/RISCV/RISCVFeatures.td
user: login: topperc
body: SiFive does not implement a TE that large so I'm a little hesitant to add an extension in our vendor namespace for it.
created_at: 2025-04-30T06:16:31Z
author_association: COLLABORATOR
diff_hunk: @@ -1197,6 +1197,73 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8f),
+                              "'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)">;
+
+def FeatureVendorXSfmm32a16f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a32f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: 32b",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+
+def FeatureVendorXSfmm32a8i
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - int: 8b",
+                     [FeatureVendorXSfmmbase]>;
+def HasVendorXSfmm32a8i : Predicate<"Subtarget->hasVendorXSfmm32a8i()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSfmm32a8i),
+                              "'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)">;
+
+def FeatureVendorXSfmm64a64f
+    : RISCVExtension<0, 6,
+                     "TEW=64-bit accumulation, operands - float: fp64",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve64d]>;
+def HasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f
+    : Predicate<"Subtarget->hasVendorXSfmm32a16fOrXSfmm32a32fOrXSfmm64a64f()">,
+                AssemblerPredicate<(any_of FeatureVendorXSfmm32a16f,
+                                           FeatureVendorXSfmm32a32f,
+                                           FeatureVendorXSfmm64a64f),
+                    "'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF)), or "
+                    "'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b), or "
+                    "'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)">;
+
+def FeatureVendorXSfmm16t
+    : RISCVExtension<0, 6,
+                     "TE=16 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl64b], "XSfmmTE", "16">;
+
+def FeatureVendorXSfmm32t
+    : RISCVExtension<0, 6,
+                     "TE=32 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl128b], "XSfmmTE", "32">;
+
+def FeatureVendorXSfmm64t
+    : RISCVExtension<0, 6,
+                     "TE=64 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl256b], "XSfmmTE", "64">;
+
+def FeatureVendorXSfmm128t
+    : RISCVExtension<0, 6,
+                     "TE=128 configuration",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZvl512b], "XSfmmTE", "128">;
path: llvm/lib/Target/RISCV/RISCVFeatures.td
user: login: sequencer
body: Thanks, that’s reasonable, we will maintain a patch based on this PR and wait for the ratification of AME or VME later. 
created_at: 2025-04-30T06:18:24Z
author_association: NONE
diff_hunk: @@ -2331,6 +2337,65 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  unsigned Widen = 0;
+  unsigned SEW = 0;
+  bool AltFmt = false;
+  StringRef Identifier;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("e"))
+    goto Fail;
+
+  if (Identifier.getAsInteger(10, SEW)) {
+    if (Identifier != "16alt")
+      goto Fail;
+
+    AltFmt = true;
+    SEW = 16;
+  }
+  if (!RISCVVType::isValidSEW(SEW))
+    goto Fail;
+
+  Lex();
+
+  if (!parseOptionalToken(AsmToken::Comma))
+    goto Fail;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("w"))
+    goto Fail;
+  if (Identifier.getAsInteger(10, Widen))
+    goto Fail;
+  if (Widen != 1 && Widen != 2 && Widen != 4)
+    goto Fail;
+
+  Lex();
+
+  if (getLexer().is(AsmToken::EndOfStatement)) {
path: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
user: login: MaskRay
body: To test whether we handle `AsmToken::EndOfStatement` properly (no duplicate \n in the output), need to have two adjacent instructions in a test
```
insn
insn
```

and check the MCAsmStreamer output
```
// CHECK:      insn
// CHECK-NEXT: insn
```
created_at: 2025-05-20T16:19:12Z
author_association: MEMBER
diff_hunk: @@ -2331,6 +2337,65 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  unsigned Widen = 0;
+  unsigned SEW = 0;
+  bool AltFmt = false;
+  StringRef Identifier;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("e"))
+    goto Fail;
+
+  if (Identifier.getAsInteger(10, SEW)) {
+    if (Identifier != "16alt")
+      goto Fail;
+
+    AltFmt = true;
+    SEW = 16;
+  }
+  if (!RISCVVType::isValidSEW(SEW))
+    goto Fail;
+
+  Lex();
+
+  if (!parseOptionalToken(AsmToken::Comma))
+    goto Fail;
+
+  if (getTok().isNot(AsmToken::Identifier))
+    goto Fail;
+
+  Identifier = getTok().getIdentifier();
+
+  if (!Identifier.consume_front("w"))
+    goto Fail;
+  if (Identifier.getAsInteger(10, Widen))
+    goto Fail;
+  if (Widen != 1 && Widen != 2 && Widen != 4)
+    goto Fail;
+
+  Lex();
+
+  if (getLexer().is(AsmToken::EndOfStatement)) {
path: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
user: login: topperc
body: I believe this check was trying to make sure there aren't additional operands left for this instruction. We're parsing multiple comma separated identifiers here as a single custom operand. Looks like we are missing a test for that.
created_at: 2025-05-20T17:06:52Z
author_association: COLLABORATOR

PR comments:
user: login: topperc
created_at: 2025-03-26T03:17:39Z
body: CC @sequencer @FantasqueX
author_association: COLLABORATOR
user: login: llvmbot
created_at: 2025-03-26T03:17:43Z
body: 
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-mc

Author: Craig Topper (topperc)

<details>
<summary>Changes</summary>

This adds assembler/disassembler support for XSfmmbase 0.6 and related SiFive matrix multiplication extensions based on the spec here https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification

Functionality-wise, this is the same as the Zvma extension proposal that SiFive shared with the Attached Matrix Extension Task Group. The extension names and instruction mnemonics have been changed to use vendor prefixes.

Note the opcodes used here are in the standard opcode space in OP-V or OP-VE.

---

Patch is 59.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133031.diff


21 Files Affected:

- (modified) clang/test/Driver/print-supported-extensions-riscv.c (+12) 
- (added) clang/test/Preprocessor/riscv-target-features-sifive.c (+95) 
- (modified) llvm/docs/RISCVUsage.rst (+3) 
- (modified) llvm/docs/ReleaseNotes.md (+2) 
- (modified) llvm/include/llvm/TargetParser/RISCVTargetParser.h (+28) 
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+89) 
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+34) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp (+14) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+80) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+1) 
- (added) llvm/lib/Target/RISCV/RISCVInstrInfoXSfmm.td (+285) 
- (modified) llvm/lib/Target/RISCV/RISCVRegisterInfo.td (+13) 
- (modified) llvm/lib/Target/RISCV/RISCVSubtarget.h (+1) 
- (modified) llvm/lib/TargetParser/RISCVTargetParser.cpp (+9) 
- (added) llvm/test/CodeGen/RISCV/attributes-sifive.ll (+58) 
- (modified) llvm/test/CodeGen/RISCV/features-info.ll (+12) 
- (modified) llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-zve64f.mir (+2-2) 
- (added) llvm/test/MC/RISCV/rvv/xsfmm-invalid.s (+36) 
- (added) llvm/test/MC/RISCV/rvv/xsfmm.s (+224) 
- (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+12) 


``````````diff
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 7e201b1149ec3..93f9e75b8413d 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -164,6 +164,18 @@
 // CHECK-NEXT:     xmipscmove           1.0       'XMIPSCMove' (MIPS conditional move instruction(s) (ccmov))
 // CHECK-NEXT:     xmipslsp             1.0       'XMIPSLSP' (MIPS optimization for hardware load-store bonding)
 // CHECK-NEXT:     xsfcease             1.0       'XSfcease' (SiFive sf.cease Instruction)
+// CHECK-NEXT:     xsfmm128t            0.6       'XSfmm128t' (TE=128 configuration)
+// CHECK-NEXT:     xsfmm16t             0.6       'XSfmm16t' (TE=16 configuration)
+// CHECK-NEXT:     xsfmm32a             0.6       'XSfmm32a' (TEW=32-bit accumulation, operands - int: 8b; float: fp16, bf16, fp32)
+// CHECK-NEXT:     xsfmm32a16f          0.6       'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF))
+// CHECK-NEXT:     xsfmm32a32f          0.6       'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b)
+// CHECK-NEXT:     xsfmm32a4i           0.6       'XSfmm32a4i' (TEW=32-bit accumulation, operands - int: 4b (packed))
+// CHECK-NEXT:     xsfmm32a8f           0.6       'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)
+// CHECK-NEXT:     xsfmm32a8i           0.6       'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)
+// CHECK-NEXT:     xsfmm32t             0.6       'XSfmm32t' (TE=32 configuration)
+// CHECK-NEXT:     xsfmm64a64f          0.6       'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)
+// CHECK-NEXT:     xsfmm64t             0.6       'XSfmm64t' (TE=64 configuration)
+// CHECK-NEXT:     xsfmmbase            0.6       'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)
 // CHECK-NEXT:     xsfvcp               1.0       'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)
 // CHECK-NEXT:     xsfvfnrclipxfqf      1.0       'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)
 // CHECK-NEXT:     xsfvfwmaccqqq        1.0       'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))
diff --git a/clang/test/Preprocessor/riscv-target-features-sifive.c b/clang/test/Preprocessor/riscv-target-features-sifive.c
new file mode 100644
index 0000000000000..a57db60a1b326
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-target-features-sifive.c
@@ -0,0 +1,95 @@
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm128t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm128t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// CHECK-XSFMM128T: __riscv_xsfmm128t  6000{{$}}
+//
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm16t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm16t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// CHECK-XSFMM16T: __riscv_xsfmm16t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A %s
+// CHECK-XSFMM32A: __riscv_xsfmm32a  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a4i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A4I %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a4i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A4I %s
+// CHECK-XSFMM32A4I: __riscv_xsfmm32a4i  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a8i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a8i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// CHECK-XSFMM32a8I: __riscv_xsfmm32a8i  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a8f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a8f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// CHECK-XSFMM32A8F: __riscv_xsfmm32a8f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a16f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a16f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// CHECK-XSFMM32a16F: __riscv_xsfmm32a16f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a32f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a32f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// CHECK-XSFMM32a32F: __riscv_xsfmm32a32f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// CHECK-XSFMM32T: __riscv_xsfmm32t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm64a64f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm64a64f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// CHECK-XSFMM64a64f: __riscv_xsfmm64a64f  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm64t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm64t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// CHECK-XSFMM64T: __riscv_xsfmm64t  6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmmbase -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmmbase -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// CHECK-XSFMMBASE: __riscv_xsfmmbase  6000{{$}}
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 8735b274a805f..1100b1a8fbe3c 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -389,6 +389,9 @@ The current vendor extensions supported are:
 ``XVentanaCondOps``
   LLVM implements `version 1.0.0 of the VTx-family custom instructions specification <https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf>`__ by Ventana Micro Systems.  All instructions are prefixed with `vt.` as described in the specification, and the riscv-toolchain-convention document linked above.  These instructions are only available for riscv64 at this time.
 
+``Xsfmm*``
+  LLVM implements `version 0.6 of the Xsfmm Family of Attached Matrix Extensions Specification <https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification>`__ by SiFive.  All instructions are prefixed with `sf.` as described in the specification.
+
 ``XSfvcp``
   LLVM implements `version 1.1.0 of the SiFive Vector Coprocessor Interface (VCIX) Software Specification <https://sifive.cdn.prismic.io/sifive/Zn3m1R5LeNNTwnLS_vcix-spec-software-v1p1.pdf>`__ by SiFive.  All instructions are prefixed with `sf.vc.` as described in the specification, and the riscv-toolchain-convention document linked above.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 445599fb9b770..b278e99d1adf3 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -152,6 +152,8 @@ Changes to the RISC-V Backend
   handlers.
 * When the experimental extension `Xqcili` is enabled, `qc.e.li` and `qc.li` may
   now be used to materialize immediates.
+* Adds experimental assembler support for the SiFive Xsfmm* Attached Matrix
+  Extensions.
 
 Changes to the WebAssembly Backend
 ----------------------------------
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index 6e231d32e7897..b4b6096f860bf 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -97,6 +97,8 @@ inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
 unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
                      bool MaskAgnostic);
 
+unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
+
 inline static VLMUL getVLMUL(unsigned VType) {
   unsigned VLMul = VType & 0x7;
   return static_cast<VLMUL>(VLMul);
@@ -126,10 +128,36 @@ inline static unsigned getSEW(unsigned VType) {
   return decodeVSEW(VSEW);
 }
 
+inline static unsigned decodeTWiden(unsigned TWiden) {
+  assert((TWiden == 1 || TWiden == 2 || TWiden == 3) &&
+         "Unexpected TWiden value");
+  return 1 << (TWiden - 1);
+}
+
+inline static bool hasXSfmmWiden(unsigned VType) {
+  unsigned TWiden = (VType >> 9) & 0x3;
+  return TWiden != 0;
+}
+
+inline static unsigned getXSfmmWiden(unsigned VType) {
+  unsigned TWiden = (VType >> 9) & 0x3;
+  assert(TWiden != 0 && "Invalid widen value");
+  return 1 << (TWiden - 1);
+}
+
+inline static bool getXSfmmAltFmt(unsigned VType) { return (VType >> 8) & 1; }
+
+static inline bool isValidXSfmmVType(unsigned VTypeI) {
+  return (VTypeI & ~0x738) == 0 && RISCVVType::hasXSfmmWiden(VTypeI) &&
+         RISCVVType::getSEW(VTypeI) * RISCVVType::getXSfmmWiden(VTypeI) <= 64;
+}
+
 inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
 
 inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
 
+inline static bool isAltFmt(unsigned VType) { return VType & 0x100; }
+
 void printVType(unsigned VType, raw_ostream &OS);
 
 unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul);
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 05997cf78c6b1..abe734b1dab20 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -77,6 +77,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
     VTypeState_Done,
   };
 
+  enum WWEEState {
+    WWEEState_Widen,
+    WWEEState_SEW,
+    WWEEState_Done,
+  };
+
   SmallVector<FeatureBitset, 4> FeatureBitStack;
 
   SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
@@ -125,6 +131,9 @@ class RISCVAsmParser : public MCTargetAsmParser {
                        bool &MaskAgnostic);
   bool generateVTypeError(SMLoc ErrorLoc);
 
+  bool parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State, unsigned &WW,
+                            unsigned &EE, bool &AltFmt);
+  bool generateXSfmmVTypeError(SMLoc ErrorLoc);
   // Helper to actually emit an instruction to the MCStreamer. Also, when
   // possible, compression of the instruction is performed.
   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
@@ -217,6 +226,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
   ParseStatus parseFenceArg(OperandVector &Operands);
   ParseStatus parseReglist(OperandVector &Operands);
   ParseStatus parseRegReg(OperandVector &Operands);
+  ParseStatus parseXSfmmVType(OperandVector &Operands);
   ParseStatus parseRetval(OperandVector &Operands);
   ParseStatus parseZcmpStackAdj(OperandVector &Operands,
                                 bool ExpectNegative = false);
@@ -622,6 +632,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return Kind == KindTy::VType;
   }
 
+  bool isXSfmmVType() const {
+    return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
+  }
+
   /// Return true if the operand is a valid for the fence instruction e.g.
   /// ('iorw').
   bool isFenceArg() const { return Kind == KindTy::Fence; }
@@ -2489,6 +2503,81 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
 }
 
+bool RISCVAsmParser::parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State,
+                                          unsigned &WW, unsigned &EE,
+                                          bool &AltFmt) {
+  if (getLexer().isNot(AsmToken::Identifier))
+    return true;
+
+  StringRef Identifier = getTok().getIdentifier();
+
+  switch (State) {
+  case WWEEState_SEW:
+    if (!Identifier.consume_front("e"))
+      break;
+    if (Identifier.getAsInteger(10, EE)) {
+      if (Identifier != "16alt")
+        break;
+
+      AltFmt = true;
+      EE = 16;
+    }
+    if (!RISCVVType::isValidSEW(EE))
+      break;
+    State = WWEEState_Widen;
+    return false;
+  case WWEEState_Widen:
+    if (!Identifier.consume_front("w"))
+      break;
+    if (Identifier.getAsInteger(10, WW))
+      break;
+    if (WW != 1 && WW != 2 && WW != 4)
+      break;
+    State = WWEEState_Done;
+    return false;
+  case WWEEState_Done:
+    // Extra token?
+    break;
+  }
+
+  return true;
+}
+
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  unsigned Widen = 0;
+  unsigned SEW = 0;
+  bool AltFmt = false;
+
+  WWEEState State = WWEEState_SEW;
+
+  if (parseXSfmmVTypeToken(getTok(), State, Widen, SEW, AltFmt))
+    return generateXSfmmVTypeError(S);
+
+  getLexer().Lex();
+
+  if (!parseOptionalToken(AsmToken::Comma))
+    return generateXSfmmVTypeError(S);
+
+  if (parseXSfmmVTypeToken(getTok(), State, Widen, SEW, AltFmt))
+    return generateXSfmmVTypeError(S);
+
+  getLexer().Lex();
+
+  if (getLexer().is(AsmToken::EndOfStatement) && State == WWEEState_Done) {
+    Operands.push_back(RISCVOperand::createVType(
+        RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
+    return ParseStatus::Success;
+  }
+
+  return generateXSfmmVTypeError(S);
+}
+
+bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
+  return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
+}
+
 ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
   if (getLexer().isNot(AsmToken::Identifier))
     return ParseStatus::NoMatch;
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 93cbf662bfa32..2c2ea82b5e892 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -323,6 +323,39 @@ static DecodeStatus DecodeVMV0RegisterClass(MCInst &Inst, uint32_t RegNo,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeTRRegisterClass(MCInst &Inst, uint32_t RegNo,
+                                          uint64_t Address,
+                                          const MCDisassembler *Decoder) {
+  if (RegNo > 15)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM2RegisterClass(MCInst &Inst, uint32_t RegNo,
+                                            uint64_t Address,
+                                            const MCDisassembler *Decoder) {
+  if (RegNo > 15 || RegNo % 2)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM4RegisterClass(MCInst &Inst, uint32_t RegNo,
+                                            uint64_t Address,
+                                            const MCDisassembler *Decoder) {
+  if (RegNo > 15 || RegNo % 4)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = RISCV::T0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeVMaskReg(MCInst &Inst, uint32_t RegNo,
                                    uint64_t Address,
                                    const MCDisassembler *Decoder) {
@@ -707,6 +740,7 @@ static constexpr DecoderListEntry DecoderList32[]{
      "XVentanaCondOps"},
     {DecoderTableXTHead32, XTHeadGroup, "T-Head extensions"},
     {DecoderTableXSfvector32, XSfVectorGroup, "SiFive vector extensions"},
+    {DecoderTableXSfmm32, {RISCV::FeatureVendorXSfmmbase}, "SiFive XSfmm"},
     {DecoderTableXSfsystem32, XSfSystemGroup, "SiFive system extensions"},
     {DecoderTableXSfcease32, {RISCV::FeatureVendorXSfcease}, "SiFive sf.cease"},
     {DecoderTableXmipslsp32, {RISCV::FeatureVendorXMIPSLSP}, "MIPS mips.lsp"},
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index a4a40862a67c6..f7aebac205ce7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -219,6 +219,20 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
   RISCVVType::printVType(Imm, O);
 }
 
+void RISCVInstPrinter::printXSfmmVType(const MCInst *MI, unsigned OpNo,
+                                       const MCSubtargetInfo &STI,
+                                       raw_ostream &O) {
+  unsigned Imm = MI->getOperand(OpNo).getImm();
+  assert(RISCVVType::isValidXSfmmVType(Imm));
+  unsigned SEW = RISCVVType::getSEW(Imm);
+  O << "e" << SEW;
+  bool AltFmt = RISCVVType::getXSfmmAltFmt(Imm);
+  if (AltFmt)
+    O << "alt";
+  unsigned Widen = RISCVVType::getXSfmmWiden(Imm);
+  O << ", w" << Widen;
+}
+
 // Print a Zcmp RList. If we are printing architectural register names rather
 // than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all
 // registers. Otherwise, we print "{ra, s0-s11}".
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
index 6d4928ee64ec9..e4846c427beb7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -48,6 +48,8 @@ class RISCVInstPrinter : public MCInstPrinter {
                             const MCSubtargetInfo &STI, raw_ostream &O);
   void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
                    raw_ostream &O);
+  void printXSfmmVType(const MCInst *MI, unsigned OpNo,
+                       const MCSubtargetInfo &STI, raw_ostream &O);
   void printVMaskReg(const MCInst *MI, unsigned OpNo,
                      const MCSubtargetInfo &STI, raw_ostream &O);
   void printRlist(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 5ed3ed917aa4c..2b42524e4fa2c 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1176,6 +1176,86 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
                       AssemblerPredicate<(all_of FeatureVendorXSfvcp),
                           "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
 
+def FeatureVendorXSfmmbase
+    : RISCVExtension<0, 6,
+                     "All non arithmetic instructions for all TEWs and sf.vtzero",
+                     [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+                         AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+                             "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+    : RISCVExtension<0, 6,
+                     "TEW=32-bit accumulation, operands - float: fp8",
+                     [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+                          AssemblerPredicate<(all_of FeatureVendorXSf...
[truncated]

``````````

</details>

author_association: MEMBER
user: login: sequencer
created_at: 2025-03-26T17:47:27Z
body: Thanks for the tests on the `rv32i`!
author_association: NONE
user: login: sequencer
created_at: 2025-03-27T11:29:01Z
body: > but won't merge them until they are ratified just like Zvzip/Zvabd/Zibimm

I think this patch is supported to be the vendor instruction set of `SiFive Xsfmm* Attached Matrix Extensions` if I understand correctly of this PR. 

AME is another issue that we don’t have ratified AME but just SiFive AME proposal, XuanTie AME proposal. 
author_association: NONE
user: login: wangpc-pp
created_at: 2025-03-27T11:51:28Z
body: > > but won't merge them until they are ratified just like Zvzip/Zvabd/Zibimm
> 
> I think this patch is supported to be the vendor instruction set of `SiFive Xsfmm* Attached Matrix Extensions` if I understand correctly of this PR.
> 
> AME is another issue that we don’t have ratified AME but just SiFive AME proposal, XuanTie AME proposal.

SiFive's AME proposal locates in OP-V/OP-VE category, I think it is not designed as vendor extension. IIUC, this patch is just for early evaluation.
author_association: CONTRIBUTOR
user: login: sequencer
created_at: 2025-03-27T11:54:56Z
body: > SiFive's AME proposal locates in OP-V/OP-VE category

Yes, this is a good point.
I do think we should also remove other vendor instruction sets which abused the standard op fields. 
author_association: NONE
user: login: topperc
created_at: 2025-03-28T21:40:58Z
body: > > SiFive's AME proposal locates in OP-V/OP-VE category
> 
> Yes, this is a good point. I do think we should also remove other vendor instruction sets which abused the standard op fields.

The RISC-V specification does not take a hard stance on non-conforming extensions. It should not be consider "abusing". Whether a non-concforming extensions is allowed is up to indvidual platform requirements. We have discussed in the past about taking patches for the T-Head 0.7 vector extension. I think we were willing to take it if there was a promise of continued maintenance.
author_association: COLLABORATOR
user: login: topperc
created_at: 2025-03-28T21:42:40Z
body: > > > but won't merge them until they are ratified just like Zvzip/Zvabd/Zibimm
> > 
> > 
> > I think this patch is supported to be the vendor instruction set of `SiFive Xsfmm* Attached Matrix Extensions` if I understand correctly of this PR.
> > AME is another issue that we don’t have ratified AME but just SiFive AME proposal, XuanTie AME proposal.
> 
> SiFive's AME proposal locates in OP-V/OP-VE category, I think it is not designed as vendor extension. IIUC, this patch is just for early evaluation.

SiFive is committed to maintaining this implementation and we would very much like to see it in tree to enable easier sharing and avoid continual rebasing. Expect to see patches for intrinsics in the near future.
author_association: COLLABORATOR
user: login: preames
created_at: 2025-03-28T22:32:03Z
body: We have discussed whether to accept non-conforming vendor extensions in the past.  Our consensus was clearly documented in RISCVUsage.rst in the statement " In particular, we expect to eventually accept both custom extensions and non-conforming extensions."

This is a non-conforming vendor extension, and that needs to be clearly described, but it is not blocking for whether we accept the change.  


author_association: COLLABORATOR
user: login: Avimitin
created_at: 2025-05-15T14:00:01Z
body: I encountered a clang compiler crash (segmentation fault) when attempting to compile the `utf8_count.c` benchmark from the `rvv-bench` project ([https://github.com/camel-cdr/rvv-bench/blob/main/bench/utf8\_count.c](https://github.com/camel-cdr/rvv-bench/blob/main/bench/utf8_count.c)) using clang build from this branch. The crash occurs during the 'RISC-V DAG-\>DAG Pattern Instruction Selection' pass.

**Steps to Reproduce:**

1.  Obtain the `utf8_count.c` file from the `rvv-bench` project (or use the minimal C code provided below).

2.  Compile the C code with the following command:

    ```bash
    riscv32-none-elf-clang -mabi=ilp32f -march=rv32imafc_xsfmm128t_zve32f_zvl2048b -mno-relax -static -nostartfiles -mcmodel=medany -fvisibility=hidden -fno-PIC -g -O3 -fno-rtti -fno-exceptions -fno-threadsafe-statics -c utf8_count.c -o utf8_count.o
    ```

**Error Log:**

<details>
<summary>Compiler Error Output</summary>

```console
$ riscv32-none-elf-clang -mabi=ilp32f -march=rv32imafc_xsfmm128t_zve32f_zvl2048b -mno-relax -static -nostartfiles -mcmodel=medany -fvisibility=hidden -fno-PIC -g -O3 -fno-rtti -fno-exceptions -fno-threadsafe-statics -c test.c -o test.o
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /nix/store/4b17xsrdcyd2bnm91pdclfw2wz3g0ikg-clang-21.0.0-unstable-2025-03-23/bin/clang @/tmp/nix-shell.VojIba/cc-params.249Z4g
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'utf8_count.c'.
4.      Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@utf8_count_SWAR_popc_bithack_autovec'
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  libLLVM.so.21.0git      0x00007fffea78aa0c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 60
1  libLLVM.so.21.0git      0x00007fffea788774 llvm::sys::CleanupOnSignal(unsigned long) + 148
2  libLLVM.so.21.0git      0x00007fffea668a88
3  libc.so.6               0x00007fffe8e40f30
4  libLLVM.so.21.0git      0x00007fffea9f4454 llvm::ScalableVectorType::get(llvm::Type*, unsigned int) + 20
5  libLLVM.so.21.0git      0x00007fffeb0d2c50 llvm::EVT::getExtendedVectorVT(llvm::LLVMContext&, llvm::EVT, llvm::ElementCount) + 48
6  libLLVM.so.21.0git      0x00007fffeb35a250
7  libLLVM.so.21.0git      0x00007fffeb35c008
8  libLLVM.so.21.0git      0x00007fffeb2fd970
9  libLLVM.so.21.0git      0x00007fffeb2fe3a9 llvm::SelectionDAG::LegalizeTypes() + 1321
10 libLLVM.so.21.0git      0x00007fffeb47af5f llvm::SelectionDAGISel::CodeGenAndEmitDAG() + 271
11 libLLVM.so.21.0git      0x00007fffeb47dc5a llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) + 5274
12 libLLVM.so.21.0git      0x00007fffeb47fb99 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 217
13 libLLVM.so.21.0git      0x00007fffeb46e8e9 llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) + 409
14 libLLVM.so.21.0git      0x00007fffead5e853
15 libLLVM.so.21.0git      0x00007fffea972d89 llvm::FPPassManager::runOnFunction(llvm::Function&) + 1705
16 libLLVM.so.21.0git      0x00007fffea972f3c llvm::FPPassManager::runOnModule(llvm::Module&) + 44
17 libLLVM.so.21.0git      0x00007fffea971f69 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 1081
18 libclang-cpp.so.21.0git 0x00007ffff5cc47f4 clang::emitBackendOutput(clang::CompilerInstance&, clang::CodeGenOptions&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) + 2772
19 libclang-cpp.so.21.0git 0x00007ffff60764bc clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 1692
20 libclang-cpp.so.21.0git 0x00007ffff4616eec clang::ParseAST(clang::Sema&, bool, bool) + 1212
21 libclang-cpp.so.21.0git 0x00007ffff6a79928 clang::FrontendAction::Execute() + 40
22 libclang-cpp.so.21.0git 0x00007ffff69eec13 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1475
23 libclang-cpp.so.21.0git 0x00007ffff6b1b11b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 539
24 clang                   0x000000000041670a cc1_main(llvm::ArrayRef<char const*>, char const*, void*) + 7306
25 clang                   0x000000000040e8f3
26 libclang-cpp.so.21.0git 0x00007ffff65d9a99
27 libLLVM.so.21.0git      0x00007fffea668e93 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) + 35
28 libclang-cpp.so.21.0git 0x00007ffff65da545
29 libclang-cpp.so.21.0git 0x00007ffff659966c clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const + 172
30 libclang-cpp.so.21.0git 0x00007ffff659a652 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const + 146
31 libclang-cpp.so.21.0git 0x00007ffff65b017c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) + 364
32 clang                   0x00000000004132f4 clang_main(int, char**, llvm::ToolContext const&) + 8308
33 clang                   0x000000000040e2b4 main + 100
34 libc.so.6               0x00007fffe8e2a1fe
35 libc.so.6               0x00007fffe8e2a2b9 __libc_start_main + 137
36 clang                   0x000000000040e315 _start + 37
clang: error: clang frontend command failed with exit code 139 (use -v to see invocation)
clang version 21.0.0git
Target: riscv32-unknown-none-elf
Thread model: posix
InstalledDir: /nix/store/4b17xsrdcyd2bnm91pdclfw2wz3g0ikg-clang-21.0.0-unstable-2025-03-23/bin
clang: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/nix-shell.VojIba/utf8_count-cefc8d.c
clang: note: diagnostic msg: /tmp/nix-shell.VojIba/utf8_count-cefc8d.sh
clang: note: diagnostic msg:

********************
```

</details>

**Minimal Reproducible C Code:**

The crash appears to be triggered by the `utf8_count_SWAR_popc_bithack_autovec` function.

<details>
<summary>Reproduce C code (test.c)</summary>

```c
#include <limits.h>
#include <stdint.h>
#include <stddef.h>
#include <float.h>

typedef uint32_t ux;

static inline int upopcnt(ux x)
{

 x -= (x >> 1) & (-(ux)1/3);

 x = (x & (-(ux)1/15*3)) + ((x >> 2) & (-(ux)1/15*3));

 x = (x + (x >> 4)) & (-(ux)1/255*15);
 ({__asm volatile("" : "+r"(x) : "r"(x) : "memory");});


 x += (x >> 8);
 x += (x >> 16);
                     ;
 return x & 127;
}

size_t utf8_count_SWAR_popc_bithack_autovec(char const *str, size_t len) {
  ux const __attribute__((__may_alias__)) * u;
  size_t count = 0, tail = 0;
  uint8_t const *u8 = (uint8_t const *)str;
  if (len < sizeof *u) {
    tail = len;
    goto skip;
  }
  tail = sizeof *u - (uintptr_t)str % sizeof *u;
  len -= tail;
  while (tail--)
    count += (*u8++ & 0xC0) != 0x80, (void)0;
  u = (ux const *)u8;
  tail = len % sizeof *u;
  for (len /= sizeof *u; len--; ++u) {
    ux b1 = ~*u & (ux)0x80808080;
    ux b2 = *u & (ux)0x40404040;
    count += upopcnt((b1 >> 1) | b2);
    (void)0;
  }
  u8 = (uint8_t const *)u;
skip:
  while (tail--)
    count += (*u8++ & 0xC0) != 0x80, (void)0;
  return count;
}

```

</details>

**Compiler Flags Used:**

```text
-mabi=ilp32f -march=rv32imafc_xsfmm128t_zve32f_zvl2048b -mno-relax -static -nostartfiles -mcmodel=medany -fvisibility=hidden -fno-PIC -g -O3 -fno-rtti -fno-exceptions -fno-threadsafe-statics
```
author_association: CONTRIBUTOR
user: login: topperc
created_at: 2025-05-16T00:43:15Z
body: @Avimitin can you please provide the 2 files indicated in the crash report

```
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/nix-shell.VojIba/utf8_count-cefc8d.c
clang: note: diagnostic msg: /tmp/nix-shell.VojIba/utf8_count-cefc8d.sh
clang: note: diagnostic msg:
````
author_association: COLLABORATOR
user: login: wangpc-pp
created_at: 2025-05-16T03:28:45Z
body: Is the issue really related to this PR? Why would a MC change cause CodeGen errors? Is it because uncommon extension combinations?
author_association: CONTRIBUTOR
user: login: Avimitin
created_at: 2025-05-16T05:47:04Z
body: > can you please provide the 2 files indicated in the crash report

Yes here is the files (Sorry GitHub doesn't support uploading code file, so I have to change them to txt suffix):
[test-ef7560.sh.txt](https://github.com/user-attachments/files/20238776/test-ef7560.sh.txt)
[test-ef7560.c.txt](https://github.com/user-attachments/files/20238777/test-ef7560.c.txt)

author_association: CONTRIBUTOR
user: login: Avimitin
created_at: 2025-05-16T05:51:58Z
body: > Is the issue really related to this PR? Why would a MC change cause CodeGen errors? Is it because uncommon extension combinations?

I've played around with the -march flag a bit more, and it doesn't seem to be the main culprit here. For example, even using `-march=rv32gc_zve32f_xsfmm128t` still leads to the same crash.

However, I've found that the optimization level seems to be the key factor. The crash happens when I use -O3 or -O2. But if I switch to -O1, -Og, or just don't specify an optimization level (which defaults to -O0), the code compiles successfully without any errors.
author_association: CONTRIBUTOR
user: login: topperc
created_at: 2025-05-16T06:05:51Z
body: > > Is the issue really related to this PR? Why would a MC change cause CodeGen errors? Is it because uncommon extension combinations?
> 
> I've played around with the -march flag a bit more, and it doesn't seem to be the main culprit here. For example, even using `-march=rv32gc_zve32f_xsfmm128t` still leads to the same crash.
> 
> However, I've found that the optimization level seems to be the key factor. The crash happens when I use -O3 or -O2. But if I switch to -O1, -Og, or just don't specify an optimization level (which defaults to -O0), the code compiles successfully without any errors.

I was able to reproduce the failure using the commit from when this PR was created. The later merge seems to have hid it. The failure still reproduces on trunk with the same IR file though.

The problem is in `combineToVCPOP` when Zve32* is enabled but not Zve64* or V*. I have a patch I'll post in a few minutes.
author_association: COLLABORATOR
user: login: topperc
created_at: 2025-05-19T17:53:42Z
body: Ping. Any further comments?
author_association: COLLABORATOR
user: login: Avimitin
created_at: 2025-05-20T13:11:37Z
body: I still get compiler error for the above case, but with additional error message:

```text
fatal error: error in backend: Invalid size request on a scalable vector.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /nix/store/n44qhrqxb3qnbylypsfq75jl2lfsvbp6-clang-21.0.0-unstable-2025-03-23/bin/clang @/tmp/nix-shell.9YUR38/cc-params.lXn6o1
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'test.c'.
4.      Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@utf8_count_SWAR_popc_bithack_autovec'
```

And here is the debug files:

[test.c.txt](https://github.com/user-attachments/files/20348260/test.c.txt)
[test.sh.txt](https://github.com/user-attachments/files/20348266/test.sh.txt)

author_association: CONTRIBUTOR
user: login: topperc
created_at: 2025-05-20T15:58:00Z
body: > I still get compiler error for the above case, but with additional error message:
> 
> ```
> fatal error: error in backend: Invalid size request on a scalable vector.
> PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
> Stack dump:
> 0.      Program arguments: /nix/store/n44qhrqxb3qnbylypsfq75jl2lfsvbp6-clang-21.0.0-unstable-2025-03-23/bin/clang @/tmp/nix-shell.9YUR38/cc-params.lXn6o1
> 1.      <eof> parser at end of file
> 2.      Code generation
> 3.      Running pass 'Function Pass Manager' on module 'test.c'.
> 4.      Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@utf8_count_SWAR_popc_bithack_autovec'
> ```
> 
> And here is the debug files:
> 
> [test.c.txt](https://github.com/user-attachments/files/20348260/test.c.txt) [test.sh.txt](https://github.com/user-attachments/files/20348266/test.sh.txt)

Please file a new issue. This error and the previous error are not related to this PR.
author_association: COLLABORATOR