[clang] [llvm] [RISCV][MC] Add experimental `Zvvmtls` and `Zvvmttls` support (PR #198229)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 4 05:25:28 PDT 2026
https://github.com/imkiva updated https://github.com/llvm/llvm-project/pull/198229
>From 4981614e2a011f0f04fb6d06eec79a2a096cea2b Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 18 May 2026 12:24:55 +0800
Subject: [PATCH 1/9] [RISCV][MC] Add experimental `Zvvmtls` and `Zvvmttls`
support
---
.../Driver/print-supported-extensions-riscv.c | 2 +
llvm/docs/RISCVUsage.rst | 11 +-
llvm/docs/ReleaseNotes.md | 2 +
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 61 +++++++++-
.../RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 14 +++
.../RISCV/MCTargetDesc/RISCVInstPrinter.h | 2 +
llvm/lib/Target/RISCV/RISCVFeatures.td | 17 +++
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 115 ++++++++++++++++++
llvm/test/CodeGen/RISCV/features-info.ll | 2 +
llvm/test/MC/RISCV/rvv/zvvmtls-invalid.s | 32 +++++
llvm/test/MC/RISCV/rvv/zvvmtls.s | 57 +++++++++
llvm/test/MC/RISCV/rvv/zvvmttls-invalid.s | 32 +++++
llvm/test/MC/RISCV/rvv/zvvmttls.s | 57 +++++++++
13 files changed, 400 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmtls-invalid.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmtls.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmttls-invalid.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmttls.s
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 6185b6a19d5e3..8cd438b797287 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -261,6 +261,8 @@
// CHECK-NEXT: zvqwbdota8i 0.2 'Zvqwbdota8i' (8-bit integer batched dot-product extension)
// CHECK-NEXT: zvvfmm 0.1 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate)
// CHECK-NEXT: zvvmm 0.1 'Zvvmm' (Integer Matrix Multiply-Accumulate)
+// CHECK-NEXT: zvvmtls 0.1 'Zvvmtls' (Matrix Tile Load/Store)
+// CHECK-NEXT: zvvmttls 0.1 'Zvvmttls' (Transposing Matrix Tile Load/Store)
// CHECK-NEXT: zvzip 0.1 'Zvzip' (Vector Reordering Structured Data)
// CHECK-NEXT: smpmpmt 0.6 'Smpmpmt' (PMP-based Memory Types Extension)
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 103c9114c272d..95d4a4271c7ca 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -258,6 +258,10 @@ on support follow.
``Zvksg`` Supported (`See note <#riscv-vector-crypto-note>`__)
``Zvksh`` Supported (`See note <#riscv-vector-crypto-note>`__)
``Zvkt`` Supported
+ ``Zvvfmm`` Assembly Support
+ ``Zvvmm`` Assembly Support
+ ``Zvvmtls`` Assembly Support
+ ``Zvvmttls`` Assembly Support
``Zvl32b`` (`Partially <#riscv-vlen-32-note>`__) Supported
``Zvl64b`` Supported
``Zvl128b`` Supported
@@ -364,10 +368,13 @@ The primary goal of experimental support is to assist in the process of ratifica
LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__.
``experimental-zvvfmm``
- LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__.
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
``experimental-zvvmm``
- LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__.
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
+
+``experimental-zvvmtls``, ``experimental-zvvmttls``
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
``experimental-zvqwbdota8i``, ``experimental-zvqwbdota16i``, ``experimental-zvfqwbdota8f``, ``experimental-zvfwbdota16bf``, ``experimental-zvfbdota32f``
LLVM implements the `0.2 draft specification <https://github.com/aswaterman/riscv-misc/blob/main/isa/ldot-bdot/ldot-bdot.adoc>`__.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index ef77fe1ba28a8..e5eeb9ba03315 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -233,6 +233,8 @@ Makes programs 10x faster by doing Special New Thing.
* Support for the experimental `XRivosVisni` vendor extension has been removed.
* Adds experimental assembler support for the 'Zvvmm` (RISC-V Integer Matrix Multiply-Accumulate) extension.
* Adds experimental assembler support for the 'Zvvfmm` (RISC-V Floating-Point Matrix Multiply-Accumulate) extension.
+* Adds experimental assembler support for the 'Zvvmtls` and 'Zvvmttls` (RISC-V
+ Matrix Tile Load/Store) extensions.
* Adds support for 'Ziccid' (Instruction/Data Coherence and Consistency) extension.
* Adds experimental assembler support for the `Xqccmt` (Qualcomm 16-bit Table Jump) vendor extension.
* `-mcpu=sifive-870` has been renamed `-mcpu=sifive-p870-d`.
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 66ed507cf36f4..58df4606ad3d2 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -207,6 +207,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseVTypeI(OperandVector &Operands);
ParseStatus parseMaskReg(OperandVector &Operands);
ParseStatus parseVScaleReg(OperandVector &Operands);
+ ParseStatus parseTileLambda(OperandVector &Operands);
ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
ParseStatus parseGPRAsFPR(OperandVector &Operands);
@@ -644,6 +645,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
}
+ bool isTileLambda() const {
+ return isUImmPred([](int64_t Imm) { return Imm >= 1 && Imm <= 7; });
+ }
+
/// Return true if the operand is a valid for the fence instruction e.g.
/// ('iorw').
bool isFenceArg() const { return Kind == KindTy::Fence; }
@@ -2552,8 +2557,13 @@ ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
return ParseStatus::NoMatch;
StringRef Name = getLexer().getTok().getIdentifier();
- if (!Name.consume_back(".t"))
- return Error(getLoc(), "expected '.t' suffix");
+ if (!Name.consume_back(".t")) {
+ // Non-register identifiers may belong to another optional operand in an
+ // overloaded mnemnoic. Let the matcher try those alternatives.
+ if (matchRegisterNameHelper(Name))
+ return Error(getLoc(), "expected '.t' suffix");
+ return ParseStatus::NoMatch;
+ }
MCRegister Reg = matchRegisterNameHelper(Name);
if (!Reg)
@@ -2587,6 +2597,53 @@ ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
return ParseStatus::Success;
}
+ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
+ if (getLexer().isNot(AsmToken::Identifier))
+ return ParseStatus::NoMatch;
+
+ SMLoc S = getLoc();
+ StringRef Name = getLexer().getTok().getIdentifier();
+ if (!Name.consume_front("L"))
+ return ParseStatus::NoMatch;
+
+ unsigned Lambda;
+ if (Name.getAsInteger(10, Lambda))
+ return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
+
+ unsigned EncodedLambda;
+ switch (Lambda) {
+ case 1:
+ EncodedLambda = 1;
+ break;
+ case 2:
+ EncodedLambda = 2;
+ break;
+ case 4:
+ EncodedLambda = 3;
+ break;
+ case 8:
+ EncodedLambda = 4;
+ break;
+ case 16:
+ EncodedLambda = 5;
+ break;
+ case 32:
+ EncodedLambda = 6;
+ break;
+ case 64:
+ EncodedLambda = 7;
+ break;
+ default:
+ return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
+ }
+
+ SMLoc E = getTok().getEndLoc();
+ getLexer().Lex();
+ Operands.push_back(RISCVOperand::createExpr(
+ MCConstantExpr::create(EncodedLambda, getContext()), S, E, isRV64()));
+ return ParseStatus::Success;
+}
+
ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
return ParseStatus::NoMatch;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index aa7ce5bf5e2a2..918dbe90bfa73 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -356,6 +356,20 @@ void RISCVInstPrinter::printVScaleReg(const MCInst *MI, unsigned OpNo,
O << ".scale";
}
+void RISCVInstPrinter::printTileLambda(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(OpNo);
+
+ assert(MO.isImm() && "printTileLambda can only print immediate operands");
+ unsigned Lambda = MO.getImm();
+ if (Lambda == 0)
+ return;
+
+ assert(Lambda <= 7 && "Unexpected tile lambda encoding");
+ O << ", L" << (1U << (Lambda - 1));
+}
+
void RISCVInstPrinter::printImm(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
index fb0598faff2be..587eb41803a45 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -54,6 +54,8 @@ class RISCVInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printVScaleReg(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
+ void printTileLambda(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printImm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
void printRegList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index ff875b745cb0e..4b0553a193bb4 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -901,6 +901,23 @@ def HasStdExtZvvfmm : Predicate<"Subtarget->hasStdExtZvvfmm()">,
AssemblerPredicate<(all_of FeatureStdExtZvvfmm),
"'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate)">;
+// Integrated Matrix Extension matrix tile load/store
+def FeatureStdExtZvvmtls
+ : RISCVExperimentalExtension<0, 1, "Matrix Tile Load/Store",
+ [FeatureStdExtZve32x]>;
+def HasStdExtZvvmtls : Predicate<"Subtarget->hasStdExtZvvmtls()">,
+ AssemblerPredicate<(all_of FeatureStdExtZvvmtls),
+ "'Zvvmtls' (Matrix Tile Load/Store)">;
+
+// Integrated Matrix Extension transposing matrix tile load/store
+def FeatureStdExtZvvmttls
+ : RISCVExperimentalExtension<0, 1,
+ "Transposing Matrix Tile Load/Store",
+ [FeatureStdExtZve32x]>;
+def HasStdExtZvvmttls : Predicate<"Subtarget->hasStdExtZvvmttls()">,
+ AssemblerPredicate<(all_of FeatureStdExtZvvmttls),
+ "'Zvvmttls' (Transposing Matrix Tile Load/Store)">;
+
// Zvbdota family of batched dot-product extensions
def FeatureStdExtZvqwbdota8i
: RISCVExperimentalExtension<0, 2,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index 0a358ba9ba0bb..b03559ab7f4f3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -16,6 +16,28 @@
// Instructions
//===----------------------------------------------------------------------===//
+def TileLambdaAsmOperand : AsmOperandClass {
+ let Name = "TileLambda";
+ let RenderMethod = "addImmOperands";
+ let ParserMethod = "parseTileLambda";
+ let DiagnosticType = "InvalidTileLambda";
+ let DiagnosticString = "operand must be L1, L2, L4, L8, L16, L32, or L64";
+}
+
+def TileLambdaOp : RISCVOp {
+ let ParserMatchClass = TileLambdaAsmOperand;
+ let PrintMethod = "printTileLambda";
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeUImmOperand<3>";
+ let OperandType = "OPERAND_UIMM3";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return Imm >= 1 && Imm <= 7;
+ }];
+}
+
def VScaleAsmOperand : AsmOperandClass {
let Name = "RVVScaleRegOpOperand";
let RenderMethod = "addRegOperands";
@@ -34,6 +56,84 @@ def VScaleOp : RegisterOperand<VMV0> {
let DecoderMethod = "decodeVMaskReg";
}
+class VTileLoadBase<bits<2> mop, dag ins, string opcodestr, string argstr>
+ : RVInst<(outs VR:$vd),
+ ins, opcodestr, argstr, [], InstFormatR> {
+ bits<5> vd;
+ bits<5> rs1;
+ bits<5> rs2;
+ bit vm;
+ bits<3> vlambda;
+
+ let Inst{31-29} = vlambda;
+ let Inst{28} = 1;
+ let Inst{27-26} = mop;
+ let Inst{25} = vm;
+ let Inst{24-20} = rs2;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = 0b111;
+ let Inst{11-7} = vd;
+ let Inst{6-0} = OPC_LOAD_FP.Value;
+
+ let mayLoad = 1;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Uses = [VL, VTYPE];
+ let VMConstraint = true;
+ let UseNamedOperandTable = true;
+}
+
+class VTileStoreBase<bits<2> mop, dag ins, string opcodestr, string argstr>
+ : RVInst<(outs),
+ ins, opcodestr, argstr, [], InstFormatR> {
+ bits<5> vs3;
+ bits<5> rs1;
+ bits<5> rs2;
+ bit vm;
+ bits<3> vlambda;
+
+ let Inst{31-29} = vlambda;
+ let Inst{28} = 1;
+ let Inst{27-26} = mop;
+ let Inst{25} = vm;
+ let Inst{24-20} = rs2;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = 0b111;
+ let Inst{11-7} = vs3;
+ let Inst{6-0} = OPC_STORE_FP.Value;
+
+ let mayLoad = 0;
+ let mayStore = 1;
+ let hasSideEffects = 0;
+ let Uses = [VL, VTYPE];
+ let UseNamedOperandTable = true;
+}
+
+class VTileLoad<bits<2> mop, string opcodestr>
+ : VTileLoadBase<mop, (ins GPRMemZeroOffset:$rs1, GPR:$rs2, VMaskOp:$vm),
+ opcodestr, "$vd, $rs1, $rs2$vm"> {
+ let vlambda = 0;
+}
+
+class VTileLoadLambda<bits<2> mop, string opcodestr>
+ : VTileLoadBase<mop, (ins GPRMemZeroOffset:$rs1, GPR:$rs2,
+ TileLambdaOp:$vlambda, VMaskOp:$vm),
+ opcodestr, "$vd, $rs1, $rs2$vlambda$vm">;
+
+class VTileStore<bits<2> mop, string opcodestr>
+ : VTileStoreBase<mop,
+ (ins VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2,
+ VMaskOp:$vm),
+ opcodestr, "$vs3, $rs1, $rs2$vm"> {
+ let vlambda = 0;
+}
+
+class VTileStoreLambda<bits<2> mop, string opcodestr>
+ : VTileStoreBase<mop,
+ (ins VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2,
+ TileLambdaOp:$vlambda, VMaskOp:$vm),
+ opcodestr, "$vs3, $rs1, $rs2$vlambda$vm">;
+
class VIMEMACVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
@@ -42,6 +142,7 @@ class VIMEMACVV<bits<6> funct6, string opcodestr>
let mayStore = 0;
let hasSideEffects = 0;
let Constraints = "$vd = $vd_wb";
+ let Uses = [VL, VTYPE];
let vm = 1;
let VMConstraint = false;
}
@@ -111,3 +212,17 @@ let Predicates = [HasStdExtZvvfmm] in {
def VFQIMMACC_VV : VIFMEMACScaleVV<0b111010, "vfqimmacc.vv">;
def VF8WIMMACC_VV : VIFMEMACScaleVV<0b111011, "vf8wimmacc.vv">;
} // Predicates = [HasStdExtZvvfmm]
+
+let Predicates = [HasStdExtZvvmtls] in {
+ def VMTL_V_L : VTileLoadLambda<0b00, "vmtl.v">, VLSSchedMC<64>;
+ def VMTL_V : VTileLoad<0b00, "vmtl.v">, VLSSchedMC<64>;
+ def VMTS_V_L : VTileStoreLambda<0b00, "vmts.v">, VSSSchedMC<64>;
+ def VMTS_V : VTileStore<0b00, "vmts.v">, VSSSchedMC<64>;
+} // Predicates = [HasStdExtZvvmtls]
+
+let Predicates = [HasStdExtZvvmttls] in {
+ def VMTTL_V_L : VTileLoadLambda<0b01, "vmttl.v">, VLSSchedMC<64>;
+ def VMTTL_V : VTileLoad<0b01, "vmttl.v">, VLSSchedMC<64>;
+ def VMTTS_V_L : VTileStoreLambda<0b01, "vmtts.v">, VSSSchedMC<64>;
+ def VMTTS_V : VTileStore<0b01, "vmtts.v">, VSSSchedMC<64>;
+} // Predicates = [HasStdExtZvvmttls]
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 610152c3a1f22..866878a06a346 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -47,6 +47,8 @@
; CHECK-NEXT: experimental-zvqwbdota8i - 'Zvqwbdota8i' (8-bit integer batched dot-product extension).
; CHECK-NEXT: experimental-zvvfmm - 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate).
; CHECK-NEXT: experimental-zvvmm - 'Zvvmm' (Integer Matrix Multiply-Accumulate).
+; CHECK-NEXT: experimental-zvvmtls - 'Zvvmtls' (Matrix Tile Load/Store).
+; CHECK-NEXT: experimental-zvvmttls - 'Zvvmttls' (Transposing Matrix Tile Load/Store).
; CHECK-NEXT: experimental-zvzip - 'Zvzip' (Vector Reordering Structured Data).
; CHECK-NEXT: f - 'F' (Single-Precision Floating-Point).
; CHECK-NEXT: forced-atomics - Assume that lock-free native-width atomics are available.
diff --git a/llvm/test/MC/RISCV/rvv/zvvmtls-invalid.s b/llvm/test/MC/RISCV/rvv/zvvmtls-invalid.s
new file mode 100644
index 0000000000000..20a5b3400097b
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmtls-invalid.s
@@ -0,0 +1,32 @@
+# RUN: not llvm-mc -triple=riscv64 --mattr=+experimental-zvvmtls %s 2>&1 \
+# RUN: | FileCheck %s
+
+vmtl.v v8, (a0), a1, L0
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtl.v v8, (a0), a1, L3
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtl.v v8, (a0), a1, L128
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtl.v v8, (a0), a1, L4, v1.t
+# CHECK: error: operand must be v0.t
+
+vmtl.v v8, (a0), a1, v0.t, L4
+# CHECK: error: invalid operand for instruction
+
+vmts.v v12, (a0), a1, L0
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmts.v v12, (a0), a1, L3
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmts.v v12, (a0), a1, L128
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmts.v v12, (a0), a1, L4, v1.t
+# CHECK: error: operand must be v0.t
+
+vmts.v v12, (a0), a1, v0.t, L4
+# CHECK: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rvv/zvvmtls.s b/llvm/test/MC/RISCV/rvv/zvvmtls.s
new file mode 100644
index 0000000000000..be00fa314dea2
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmtls.s
@@ -0,0 +1,57 @@
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvmtls %s \
+# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvmtls %s \
+# RUN: | llvm-objdump -d --mattr=+experimental-zvvmtls - \
+# RUN: | FileCheck %s --check-prefix=CHECK-INST
+
+vmtl.v v8, (a0), a1
+# CHECK-INST: vmtl.v v8, (a0), a1
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x12]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmtl.v v8, (a0), a1, L4
+# CHECK-INST: vmtl.v v8, (a0), a1, L4
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x72]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmtl.v v8, (a0), a1, v0.t
+# CHECK-INST: vmtl.v v8, (a0), a1, v0.t
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x10]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmtl.v v8, (a0), a1, L4, v0.t
+# CHECK-INST: vmtl.v v8, (a0), a1, L4, v0.t
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x70]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmtl.v v8, (a0), zero, L64, v0.t
+# CHECK-INST: vmtl.v v8, (a0), zero, L64, v0.t
+# CHECK-ENCODING: [0x07,0x74,0x05,0xf0]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmts.v v12, (a0), a1
+# CHECK-INST: vmts.v v12, (a0), a1
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x12]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmts.v v12, (a0), a1, L4
+# CHECK-INST: vmts.v v12, (a0), a1, L4
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x72]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmts.v v12, (a0), a1, v0.t
+# CHECK-INST: vmts.v v12, (a0), a1, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x10]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmts.v v12, (a0), a1, L4, v0.t
+# CHECK-INST: vmts.v v12, (a0), a1, L4, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x70]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
+vmts.v v12, (a0), zero, L64, v0.t
+# CHECK-INST: vmts.v v12, (a0), zero, L64, v0.t
+# CHECK-ENCODING: [0x27,0x76,0x05,0xf0]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
diff --git a/llvm/test/MC/RISCV/rvv/zvvmttls-invalid.s b/llvm/test/MC/RISCV/rvv/zvvmttls-invalid.s
new file mode 100644
index 0000000000000..226680f32b7c5
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmttls-invalid.s
@@ -0,0 +1,32 @@
+# RUN: not llvm-mc -triple=riscv64 --mattr=+experimental-zvvmttls %s 2>&1 \
+# RUN: | FileCheck %s
+
+vmttl.v v8, (a0), a1, L0
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmttl.v v8, (a0), a1, L3
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmttl.v v8, (a0), a1, L128
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmttl.v v8, (a0), a1, L4, v1.t
+# CHECK: error: operand must be v0.t
+
+vmttl.v v8, (a0), a1, v0.t, L4
+# CHECK: error: invalid operand for instruction
+
+vmtts.v v12, (a0), a1, L0
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtts.v v12, (a0), a1, L3
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtts.v v12, (a0), a1, L128
+# CHECK: error: operand must be L1, L2, L4, L8, L16, L32, or L64
+
+vmtts.v v12, (a0), a1, L4, v1.t
+# CHECK: error: operand must be v0.t
+
+vmtts.v v12, (a0), a1, v0.t, L4
+# CHECK: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rvv/zvvmttls.s b/llvm/test/MC/RISCV/rvv/zvvmttls.s
new file mode 100644
index 0000000000000..07c6b1cbce243
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmttls.s
@@ -0,0 +1,57 @@
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvmttls %s \
+# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvmttls %s \
+# RUN: | llvm-objdump -d --mattr=+experimental-zvvmttls - \
+# RUN: | FileCheck %s --check-prefix=CHECK-INST
+
+vmttl.v v8, (a0), a1
+# CHECK-INST: vmttl.v v8, (a0), a1
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x16]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmttl.v v8, (a0), a1, L4
+# CHECK-INST: vmttl.v v8, (a0), a1, L4
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x76]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmttl.v v8, (a0), a1, v0.t
+# CHECK-INST: vmttl.v v8, (a0), a1, v0.t
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x14]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmttl.v v8, (a0), a1, L4, v0.t
+# CHECK-INST: vmttl.v v8, (a0), a1, L4, v0.t
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x74]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmttl.v v8, (a0), zero, L64, v0.t
+# CHECK-INST: vmttl.v v8, (a0), zero, L64, v0.t
+# CHECK-ENCODING: [0x07,0x74,0x05,0xf4]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmtts.v v12, (a0), a1
+# CHECK-INST: vmtts.v v12, (a0), a1
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x16]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmtts.v v12, (a0), a1, L4
+# CHECK-INST: vmtts.v v12, (a0), a1, L4
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x76]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmtts.v v12, (a0), a1, v0.t
+# CHECK-INST: vmtts.v v12, (a0), a1, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x14]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmtts.v v12, (a0), a1, L4, v0.t
+# CHECK-INST: vmtts.v v12, (a0), a1, L4, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x74]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
+vmtts.v v12, (a0), zero, L64, v0.t
+# CHECK-INST: vmtts.v v12, (a0), zero, L64, v0.t
+# CHECK-ENCODING: [0x27,0x76,0x05,0xf4]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
>From 85699b55dddc97ed6bc47ef7562f716ff26a0db7 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 18 May 2026 12:42:13 +0800
Subject: [PATCH 2/9] Update docs
---
llvm/docs/RISCVUsage.rst | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 95d4a4271c7ca..d8c7642da35df 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -373,7 +373,10 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zvvmm``
LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
-``experimental-zvvmtls``, ``experimental-zvvmttls``
+``experimental-zvvmtls``
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
+
+``experimental-zvvmttls``
LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-71c48b9-2026-05-17>`__.
``experimental-zvqwbdota8i``, ``experimental-zvqwbdota16i``, ``experimental-zvfqwbdota8f``, ``experimental-zvfwbdota16bf``, ``experimental-zvfbdota32f``
>From 097fd247a785ab750858870151095fa1a5145e3a Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 18 May 2026 12:45:13 +0800
Subject: [PATCH 3/9] Update docs
---
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index b03559ab7f4f3..ea33880972b04 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -214,15 +214,15 @@ let Predicates = [HasStdExtZvvfmm] in {
} // Predicates = [HasStdExtZvvfmm]
let Predicates = [HasStdExtZvvmtls] in {
- def VMTL_V_L : VTileLoadLambda<0b00, "vmtl.v">, VLSSchedMC<64>;
- def VMTL_V : VTileLoad<0b00, "vmtl.v">, VLSSchedMC<64>;
- def VMTS_V_L : VTileStoreLambda<0b00, "vmts.v">, VSSSchedMC<64>;
- def VMTS_V : VTileStore<0b00, "vmts.v">, VSSSchedMC<64>;
+ def VMTL_V_L : VTileLoadLambda<0b00, "vmtl.v">;
+ def VMTL_V : VTileLoad<0b00, "vmtl.v">;
+ def VMTS_V_L : VTileStoreLambda<0b00, "vmts.v">;
+ def VMTS_V : VTileStore<0b00, "vmts.v">;
} // Predicates = [HasStdExtZvvmtls]
let Predicates = [HasStdExtZvvmttls] in {
- def VMTTL_V_L : VTileLoadLambda<0b01, "vmttl.v">, VLSSchedMC<64>;
- def VMTTL_V : VTileLoad<0b01, "vmttl.v">, VLSSchedMC<64>;
- def VMTTS_V_L : VTileStoreLambda<0b01, "vmtts.v">, VSSSchedMC<64>;
- def VMTTS_V : VTileStore<0b01, "vmtts.v">, VSSSchedMC<64>;
+ def VMTTL_V_L : VTileLoadLambda<0b01, "vmttl.v">;
+ def VMTTL_V : VTileLoad<0b01, "vmttl.v">;
+ def VMTTS_V_L : VTileStoreLambda<0b01, "vmtts.v">;
+ def VMTTS_V : VTileStore<0b01, "vmtts.v">;
} // Predicates = [HasStdExtZvvmttls]
>From 917f4f0f5091fd0bcbc3058adec96e67eab8356b Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 18 May 2026 14:52:33 +0800
Subject: [PATCH 4/9] Review
---
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 30 ++-------------
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 38 +++++++++----------
.../TargetParser/RISCVISAInfoTest.cpp | 2 +
3 files changed, 25 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 58df4606ad3d2..63e36cd1665f6 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -646,7 +646,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}
bool isTileLambda() const {
- return isUImmPred([](int64_t Imm) { return Imm >= 1 && Imm <= 7; });
+ return isUImmPred([](int64_t Imm) { return Imm && isUInt<3>(Imm); });
}
/// Return true if the operand is a valid for the fence instruction e.g.
@@ -2610,32 +2610,10 @@ ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
if (Name.getAsInteger(10, Lambda))
return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
- unsigned EncodedLambda;
- switch (Lambda) {
- case 1:
- EncodedLambda = 1;
- break;
- case 2:
- EncodedLambda = 2;
- break;
- case 4:
- EncodedLambda = 3;
- break;
- case 8:
- EncodedLambda = 4;
- break;
- case 16:
- EncodedLambda = 5;
- break;
- case 32:
- EncodedLambda = 6;
- break;
- case 64:
- EncodedLambda = 7;
- break;
- default:
+ if (!isPowerOf2_32(Lambda) || Lambda >= 128)
return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
- }
+
+ unsigned EncodedLambda = Log2_32(Lambda) + 1;
SMLoc E = getTok().getEndLoc();
getLexer().Lex();
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index ea33880972b04..23e69eaf7a24b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -34,7 +34,7 @@ def TileLambdaOp : RISCVOp {
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
- return Imm >= 1 && Imm <= 7;
+ return Imm && isUInt<3>(Imm);
}];
}
@@ -75,9 +75,9 @@ class VTileLoadBase<bits<2> mop, dag ins, string opcodestr, string argstr>
let Inst{11-7} = vd;
let Inst{6-0} = OPC_LOAD_FP.Value;
- let mayLoad = 1;
- let mayStore = 0;
- let hasSideEffects = 0;
+ let mayLoad = true;
+ let mayStore = false;
+ let hasSideEffects = false;
let Uses = [VL, VTYPE];
let VMConstraint = true;
let UseNamedOperandTable = true;
@@ -102,9 +102,9 @@ class VTileStoreBase<bits<2> mop, dag ins, string opcodestr, string argstr>
let Inst{11-7} = vs3;
let Inst{6-0} = OPC_STORE_FP.Value;
- let mayLoad = 0;
- let mayStore = 1;
- let hasSideEffects = 0;
+ let mayLoad = false;
+ let mayStore = true;
+ let hasSideEffects = false;
let Uses = [VL, VTYPE];
let UseNamedOperandTable = true;
}
@@ -138,9 +138,9 @@ class VIMEMACVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
"$vd, $vs1, $vs2"> {
- let mayLoad = 0;
- let mayStore = 0;
- let hasSideEffects = 0;
+ let mayLoad = false;
+ let mayStore = false;
+ let hasSideEffects = false;
let Constraints = "$vd = $vd_wb";
let Uses = [VL, VTYPE];
let vm = 1;
@@ -151,9 +151,9 @@ class VFMEMACVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPFVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
"$vd, $vs1, $vs2"> {
- let mayLoad = 0;
- let mayStore = 0;
- let hasSideEffects = 0;
+ let mayLoad = false;
+ let mayStore = false;
+ let hasSideEffects = false;
let Constraints = "$vd = $vd_wb";
let Uses = [FRM, VL, VTYPE];
let mayRaiseFPException = true;
@@ -165,9 +165,9 @@ class VFMEMACScaleVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPFVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr,
"$vd, $vs1, $vs2$vm"> {
- let mayLoad = 0;
- let mayStore = 0;
- let hasSideEffects = 0;
+ let mayLoad = false;
+ let mayStore = false;
+ let hasSideEffects = false;
let Constraints = "$vd = $vd_wb";
let Uses = [FRM, VL, VTYPE];
let mayRaiseFPException = true;
@@ -179,9 +179,9 @@ class VIFMEMACScaleVV<bits<6> funct6, string opcodestr>
: RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
(ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr,
"$vd, $vs1, $vs2$vm"> {
- let mayLoad = 0;
- let mayStore = 0;
- let hasSideEffects = 0;
+ let mayLoad = false;
+ let mayStore = false;
+ let hasSideEffects = false;
let Constraints = "$vd = $vd_wb";
let Uses = [FRM, VL, VTYPE];
let mayRaiseFPException = true;
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index a1702af0f5325..87539f4dd98f7 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1397,6 +1397,8 @@ Experimental extensions
zvqwbdota8i 0.2
zvvfmm 0.1
zvvmm 0.1
+ zvvmtls 0.1
+ zvvmttls 0.1
zvzip 0.1
smpmpmt 0.6
svukte 0.3
>From 0287a01dea821c0ceda27fc5ae80be27ccc414d8 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Tue, 19 May 2026 16:30:53 +0800
Subject: [PATCH 5/9] Review
---
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 8 +++-----
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 11 ++---------
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 63e36cd1665f6..5b78b5ce089e5 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -2559,7 +2559,7 @@ ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
StringRef Name = getLexer().getTok().getIdentifier();
if (!Name.consume_back(".t")) {
// Non-register identifiers may belong to another optional operand in an
- // overloaded mnemnoic. Let the matcher try those alternatives.
+ // overloaded mnemonic. Let the matcher try those alternatives.
if (matchRegisterNameHelper(Name))
return Error(getLoc(), "expected '.t' suffix");
return ParseStatus::NoMatch;
@@ -2607,10 +2607,8 @@ ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
return ParseStatus::NoMatch;
unsigned Lambda;
- if (Name.getAsInteger(10, Lambda))
- return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
-
- if (!isPowerOf2_32(Lambda) || Lambda >= 128)
+ if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) ||
+ Lambda >= 128)
return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
unsigned EncodedLambda = Log2_32(Lambda) + 1;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index 23e69eaf7a24b..a630eb1d35deb 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -28,14 +28,8 @@ def TileLambdaOp : RISCVOp {
let ParserMatchClass = TileLambdaAsmOperand;
let PrintMethod = "printTileLambda";
let EncoderMethod = "getImmOpValue";
- let DecoderMethod = "decodeUImmOperand<3>";
+ let DecoderMethod = "decodeUImmNonZeroOperand<3>";
let OperandType = "OPERAND_UIMM3";
- let MCOperandPredicate = [{
- int64_t Imm;
- if (!MCOp.evaluateAsConstantImm(Imm))
- return false;
- return Imm && isUInt<3>(Imm);
- }];
}
def VScaleAsmOperand : AsmOperandClass {
@@ -84,8 +78,7 @@ class VTileLoadBase<bits<2> mop, dag ins, string opcodestr, string argstr>
}
class VTileStoreBase<bits<2> mop, dag ins, string opcodestr, string argstr>
- : RVInst<(outs),
- ins, opcodestr, argstr, [], InstFormatR> {
+ : RVInst<(outs), ins, opcodestr, argstr, [], InstFormatR> {
bits<5> vs3;
bits<5> rs1;
bits<5> rs2;
>From 2d63096f9cc6e7f88deeffebcdf22ee3c356c6cc Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Tue, 19 May 2026 16:35:45 +0800
Subject: [PATCH 6/9] Format
---
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5b78b5ce089e5..373a520fa2f7e 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -2607,8 +2607,7 @@ ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
return ParseStatus::NoMatch;
unsigned Lambda;
- if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) ||
- Lambda >= 128)
+ if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) || Lambda >= 128)
return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
unsigned EncodedLambda = Log2_32(Lambda) + 1;
>From 19e38a3d70bffc34815812cfd2179c147443716f Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Tue, 2 Jun 2026 12:05:47 +0800
Subject: [PATCH 7/9] Add OPERAND_UIMM3_NONZERO
---
llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 1 +
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 +++
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 2 +-
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 7f1aa83075f1f..f5773083ee367 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -32,6 +32,7 @@ enum OperandType : unsigned {
OPERAND_UIMM2,
OPERAND_UIMM2_LSB0,
OPERAND_UIMM3,
+ OPERAND_UIMM3_NONZERO,
OPERAND_UIMM4,
OPERAND_UIMM4_PLUS1,
OPERAND_UIMM5,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index c622d188c67a1..cbb4d1d16a038 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3030,6 +3030,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
CASE_OPERAND_UIMM_LSB_ZEROS(8, 000)
CASE_OPERAND_UIMM_LSB_ZEROS(9, 000)
// clang-format on
+ case RISCVOp::OPERAND_UIMM3_NONZERO:
+ Ok = isUInt<3>(Imm) && (Imm != 0);
+ break;
case RISCVOp::OPERAND_UIMM5_NONZERO:
Ok = isUInt<5>(Imm) && (Imm != 0);
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index a630eb1d35deb..5f63d33e819bc 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -29,7 +29,7 @@ def TileLambdaOp : RISCVOp {
let PrintMethod = "printTileLambda";
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmNonZeroOperand<3>";
- let OperandType = "OPERAND_UIMM3";
+ let OperandType = "OPERAND_UIMM3_NONZERO";
}
def VScaleAsmOperand : AsmOperandClass {
>From 5588da74a4067637c91d170da04a050b5a6cf075 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Tue, 2 Jun 2026 20:32:52 +0800
Subject: [PATCH 8/9] Support lowercase lambda tile
---
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 2 +-
llvm/test/MC/RISCV/rvv/zvvmtls.s | 10 ++++++++++
llvm/test/MC/RISCV/rvv/zvvmttls.s | 10 ++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 373a520fa2f7e..79ddd1ac9fe7f 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -2603,7 +2603,7 @@ ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
SMLoc S = getLoc();
StringRef Name = getLexer().getTok().getIdentifier();
- if (!Name.consume_front("L"))
+ if (!Name.consume_front("L") && !Name.consume_front("l"))
return ParseStatus::NoMatch;
unsigned Lambda;
diff --git a/llvm/test/MC/RISCV/rvv/zvvmtls.s b/llvm/test/MC/RISCV/rvv/zvvmtls.s
index be00fa314dea2..54a91f6a4d25e 100644
--- a/llvm/test/MC/RISCV/rvv/zvvmtls.s
+++ b/llvm/test/MC/RISCV/rvv/zvvmtls.s
@@ -16,6 +16,11 @@ vmtl.v v8, (a0), a1, L4
# CHECK-ENCODING: [0x07,0x74,0xb5,0x72]
# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+vmtl.v v8, (a0), a1, l2
+# CHECK-INST: vmtl.v v8, (a0), a1, L2
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x52]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
vmtl.v v8, (a0), a1, v0.t
# CHECK-INST: vmtl.v v8, (a0), a1, v0.t
# CHECK-ENCODING: [0x07,0x74,0xb5,0x10]
@@ -51,6 +56,11 @@ vmts.v v12, (a0), a1, L4, v0.t
# CHECK-ENCODING: [0x27,0x76,0xb5,0x70]
# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+vmts.v v12, (a0), a1, l2, v0.t
+# CHECK-INST: vmts.v v12, (a0), a1, L2, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x50]
+# CHECK-ERROR: instruction requires the following: 'Zvvmtls' (Matrix Tile Load/Store){{$}}
+
vmts.v v12, (a0), zero, L64, v0.t
# CHECK-INST: vmts.v v12, (a0), zero, L64, v0.t
# CHECK-ENCODING: [0x27,0x76,0x05,0xf0]
diff --git a/llvm/test/MC/RISCV/rvv/zvvmttls.s b/llvm/test/MC/RISCV/rvv/zvvmttls.s
index 07c6b1cbce243..68a47844ee56f 100644
--- a/llvm/test/MC/RISCV/rvv/zvvmttls.s
+++ b/llvm/test/MC/RISCV/rvv/zvvmttls.s
@@ -16,6 +16,11 @@ vmttl.v v8, (a0), a1, L4
# CHECK-ENCODING: [0x07,0x74,0xb5,0x76]
# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+vmttl.v v8, (a0), a1, l2
+# CHECK-INST: vmttl.v v8, (a0), a1, L2
+# CHECK-ENCODING: [0x07,0x74,0xb5,0x56]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
vmttl.v v8, (a0), a1, v0.t
# CHECK-INST: vmttl.v v8, (a0), a1, v0.t
# CHECK-ENCODING: [0x07,0x74,0xb5,0x14]
@@ -51,6 +56,11 @@ vmtts.v v12, (a0), a1, L4, v0.t
# CHECK-ENCODING: [0x27,0x76,0xb5,0x74]
# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+vmtts.v v12, (a0), a1, l2, v0.t
+# CHECK-INST: vmtts.v v12, (a0), a1, L2, v0.t
+# CHECK-ENCODING: [0x27,0x76,0xb5,0x54]
+# CHECK-ERROR: instruction requires the following: 'Zvvmttls' (Transposing Matrix Tile Load/Store){{$}}
+
vmtts.v v12, (a0), zero, L64, v0.t
# CHECK-INST: vmtts.v v12, (a0), zero, L64, v0.t
# CHECK-ENCODING: [0x27,0x76,0x05,0xf4]
>From c3fbb7f731f29dc992e6f83ce09132c3f7683564 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Thu, 4 Jun 2026 20:24:55 +0800
Subject: [PATCH 9/9] Use InstAlias with EmitPriority=0 to handle optional
lambda tile
---
.../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 1 -
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 --
llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 34 ++++++++-----------
3 files changed, 14 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index f5773083ee367..7f1aa83075f1f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -32,7 +32,6 @@ enum OperandType : unsigned {
OPERAND_UIMM2,
OPERAND_UIMM2_LSB0,
OPERAND_UIMM3,
- OPERAND_UIMM3_NONZERO,
OPERAND_UIMM4,
OPERAND_UIMM4_PLUS1,
OPERAND_UIMM5,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index cbb4d1d16a038..c622d188c67a1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3030,9 +3030,6 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
CASE_OPERAND_UIMM_LSB_ZEROS(8, 000)
CASE_OPERAND_UIMM_LSB_ZEROS(9, 000)
// clang-format on
- case RISCVOp::OPERAND_UIMM3_NONZERO:
- Ok = isUInt<3>(Imm) && (Imm != 0);
- break;
case RISCVOp::OPERAND_UIMM5_NONZERO:
Ok = isUInt<5>(Imm) && (Imm != 0);
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
index 5f63d33e819bc..067a9c0e404d4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td
@@ -28,8 +28,8 @@ def TileLambdaOp : RISCVOp {
let ParserMatchClass = TileLambdaAsmOperand;
let PrintMethod = "printTileLambda";
let EncoderMethod = "getImmOpValue";
- let DecoderMethod = "decodeUImmNonZeroOperand<3>";
- let OperandType = "OPERAND_UIMM3_NONZERO";
+ let DecoderMethod = "decodeUImmOperand<3>";
+ let OperandType = "OPERAND_UIMM3";
}
def VScaleAsmOperand : AsmOperandClass {
@@ -103,25 +103,11 @@ class VTileStoreBase<bits<2> mop, dag ins, string opcodestr, string argstr>
}
class VTileLoad<bits<2> mop, string opcodestr>
- : VTileLoadBase<mop, (ins GPRMemZeroOffset:$rs1, GPR:$rs2, VMaskOp:$vm),
- opcodestr, "$vd, $rs1, $rs2$vm"> {
- let vlambda = 0;
-}
-
-class VTileLoadLambda<bits<2> mop, string opcodestr>
: VTileLoadBase<mop, (ins GPRMemZeroOffset:$rs1, GPR:$rs2,
TileLambdaOp:$vlambda, VMaskOp:$vm),
opcodestr, "$vd, $rs1, $rs2$vlambda$vm">;
class VTileStore<bits<2> mop, string opcodestr>
- : VTileStoreBase<mop,
- (ins VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2,
- VMaskOp:$vm),
- opcodestr, "$vs3, $rs1, $rs2$vm"> {
- let vlambda = 0;
-}
-
-class VTileStoreLambda<bits<2> mop, string opcodestr>
: VTileStoreBase<mop,
(ins VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2,
TileLambdaOp:$vlambda, VMaskOp:$vm),
@@ -207,15 +193,23 @@ let Predicates = [HasStdExtZvvfmm] in {
} // Predicates = [HasStdExtZvvfmm]
let Predicates = [HasStdExtZvvmtls] in {
- def VMTL_V_L : VTileLoadLambda<0b00, "vmtl.v">;
def VMTL_V : VTileLoad<0b00, "vmtl.v">;
- def VMTS_V_L : VTileStoreLambda<0b00, "vmts.v">;
def VMTS_V : VTileStore<0b00, "vmts.v">;
+ def : InstAlias<"vmtl.v $vd, $rs1, $rs2$vm",
+ (VMTL_V VR:$vd, GPRMemZeroOffset:$rs1, GPR:$rs2, 0,
+ VMaskOp:$vm), 0>;
+ def : InstAlias<"vmts.v $vs3, $rs1, $rs2$vm",
+ (VMTS_V VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2, 0,
+ VMaskOp:$vm), 0>;
} // Predicates = [HasStdExtZvvmtls]
let Predicates = [HasStdExtZvvmttls] in {
- def VMTTL_V_L : VTileLoadLambda<0b01, "vmttl.v">;
def VMTTL_V : VTileLoad<0b01, "vmttl.v">;
- def VMTTS_V_L : VTileStoreLambda<0b01, "vmtts.v">;
def VMTTS_V : VTileStore<0b01, "vmtts.v">;
+ def : InstAlias<"vmttl.v $vd, $rs1, $rs2$vm",
+ (VMTTL_V VR:$vd, GPRMemZeroOffset:$rs1, GPR:$rs2, 0,
+ VMaskOp:$vm), 0>;
+ def : InstAlias<"vmtts.v $vs3, $rs1, $rs2$vm",
+ (VMTTS_V VR:$vs3, GPRMemZeroOffset:$rs1, GPR:$rs2, 0,
+ VMaskOp:$vm), 0>;
} // Predicates = [HasStdExtZvvmttls]
More information about the cfe-commits
mailing list