[clang] [llvm] [RISCV][MC] Add experimental `Zvvmm` MC support (PR #193956)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 27 04:04:31 PDT 2026
https://github.com/imkiva updated https://github.com/llvm/llvm-project/pull/193956
>From 6ed33e6ddee6cbdef724fc0e6e682cecd1034dcd Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 24 Apr 2026 20:25:30 +0800
Subject: [PATCH 1/6] [RISCV][Zvvmm] Define experimental zvvmm extension
---
.../llvm/TargetParser/RISCVTargetParser.h | 29 ++++++
llvm/lib/Target/RISCV/RISCVFeatures.td | 8 ++
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 1 +
llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td | 49 +++++++++++
llvm/lib/TargetParser/RISCVTargetParser.cpp | 88 +++++++++++++++++++
.../TargetParser/RISCVISAInfoTest.cpp | 1 +
.../TargetParser/RISCVTargetParserTest.cpp | 51 +++++++++++
7 files changed, 227 insertions(+)
create mode 100644 llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index 110b71a6341a6..d0f4bc0795793 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -19,6 +19,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <optional>
namespace llvm {
@@ -128,6 +129,34 @@ LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
+inline static bool isValidIMELambda(unsigned Lambda) {
+ return Lambda == 0 || (isPowerOf2_32(Lambda) && Lambda <= 64);
+}
+
+LLVM_ABI unsigned encodeIMELambda(unsigned Lambda);
+
+LLVM_ABI std::optional<unsigned> decodeIMELambda(unsigned Encoding);
+
+LLVM_ABI uint64_t getIMEVTypeFieldsMask(unsigned XLen);
+
+LLVM_ABI uint64_t encodeIMEVTypeFields(unsigned XLen, unsigned Lambda,
+ bool AltFmtA, bool AltFmtB,
+ bool BlockSize16);
+
+LLVM_ABI uint64_t addIMEVTypeFields(uint64_t VType, unsigned XLen,
+ unsigned Lambda, bool AltFmtA, bool AltFmtB,
+ bool BlockSize16);
+
+LLVM_ABI unsigned getIMELambdaEncoding(uint64_t VType, unsigned XLen);
+
+LLVM_ABI std::optional<unsigned> getIMELambda(uint64_t VType, unsigned XLen);
+
+LLVM_ABI bool isIMEAltFmtA(uint64_t VType, unsigned XLen);
+
+LLVM_ABI bool isIMEAltFmtB(uint64_t VType, unsigned XLen);
+
+LLVM_ABI bool isIMEBlockSize16(uint64_t VType, unsigned XLen);
+
inline static VLMUL getVLMUL(unsigned VType) {
unsigned VLMul = VType & 0x7;
return static_cast<VLMUL>(VLMul);
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 825c78509519d..b905870a482ff 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -885,6 +885,14 @@ def HasStdExtZvzip : Predicate<"Subtarget->hasStdExtZvzip()">,
AssemblerPredicate<(all_of FeatureStdExtZvzip),
"'Zvzip' (Vector Reordering Structured Data)">;
+// Integrated Matrix Extension integer matrix multiply-accumulate
+def FeatureStdExtZvvmm
+ : RISCVExperimentalExtension<0, 1, "Integer Matrix Multiply-Accumulate",
+ [FeatureStdExtZve32x]>;
+def HasStdExtZvvmm : Predicate<"Subtarget->hasStdExtZvvmm()">,
+ AssemblerPredicate<(all_of FeatureStdExtZvvmm),
+ "'Zvvmm' (Integer Matrix Multiply-Accumulate)">;
+
// Vector instruction predicates
def HasVInstructions : Predicate<"Subtarget->hasVInstructions()">,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index b2488435cf81e..b08164c088f58 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2358,6 +2358,7 @@ include "RISCVInstrInfoZvk.td"
include "RISCVInstrInfoZvdot4a8i.td"
include "RISCVInstrInfoZvfofp8min.td"
include "RISCVInstrInfoZvzip.td"
+include "RISCVInstrInfoZvvmm.td"
// Packed SIMD
include "RISCVInstrInfoP.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
new file mode 100644
index 0000000000000..c4dd6267daa19
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
@@ -0,0 +1,49 @@
+//===---- RISCVInstrInfoZvvmm.td - 'Zvvmm' instructions -*- 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 RISC-V instructions from the standard 'Zvvmm'
+// extension for integer matrix multiply-accumulate.
+// This version is still experimental as the 'Zvvmm' extension hasn't been
+// ratified yet.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+class VIMEMACVV<bits<6> funct6, string opcodestr>
+ : RVInstVV<funct6, OPIVV, (outs VR:$vd_wb),
+ (ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr,
+ "$vd, $vs1, $vs2"> {
+ let mayLoad = 0;
+ let mayStore = 0;
+ let hasSideEffects = 0;
+ let Constraints = "$vd = $vd_wb";
+ let vm = 1;
+ let VMConstraint = false;
+}
+
+let Predicates = [HasStdExtZvvmm] in {
+ def VMMACC_VV
+ : VIMEMACVV<0b111000, "vmmacc.vv">,
+ SchedTernaryMC<"WriteVIMulAddV", "ReadVIMulAddV", "ReadVIMulAddV",
+ "ReadVIMulAddV", forceMasked=0>;
+ def VWMMACC_VV
+ : VIMEMACVV<0b111001, "vwmmacc.vv">,
+ SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
+ "ReadVIWMulAddV", forceMasked=0>;
+ def VQMMACC_VV
+ : VIMEMACVV<0b111010, "vqmmacc.vv">,
+ SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
+ "ReadVIWMulAddV", forceMasked=0>;
+ def V8WMMACC_VV
+ : VIMEMACVV<0b111011, "v8wmmacc.vv">,
+ SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
+ "ReadVIWMulAddV", forceMasked=0>;
+} // Predicates = [HasStdExtZvvmm]
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index eef426d7c9aee..7fc1b7e38da45 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -388,6 +388,94 @@ unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt) {
return VTypeI;
}
+static void assertValidXLenForIMEVType(unsigned XLen) {
+ assert((XLen == 32 || XLen == 64) && "Invalid XLEN");
+}
+
+static unsigned getIMELambdaShift(unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return XLen - 4;
+}
+
+static unsigned getIMEAltFmtAShift(unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return XLen - 5;
+}
+
+static unsigned getIMEAltFmtBShift(unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return XLen - 6;
+}
+
+static unsigned getIMEBSShift(unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return XLen - 7;
+}
+
+unsigned encodeIMELambda(unsigned Lambda) {
+ assert(isValidIMELambda(Lambda) && "Invalid IME lambda");
+ if (Lambda == 0)
+ return 0;
+ return Log2_32(Lambda) + 1;
+}
+
+std::optional<unsigned> decodeIMELambda(unsigned Encoding) {
+ assert(Encoding < 8 && "Invalid IME lambda encoding");
+ if (Encoding == 0)
+ return std::nullopt;
+ return 1U << (Encoding - 1);
+}
+
+uint64_t getIMEVTypeFieldsMask(unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return (0x7ULL << getIMELambdaShift(XLen)) |
+ (1ULL << getIMEAltFmtAShift(XLen)) |
+ (1ULL << getIMEAltFmtBShift(XLen)) | (1ULL << getIMEBSShift(XLen));
+}
+
+uint64_t encodeIMEVTypeFields(unsigned XLen, unsigned Lambda, bool AltFmtA,
+ bool AltFmtB, bool BlockSize16) {
+ assertValidXLenForIMEVType(XLen);
+ uint64_t VType = uint64_t(encodeIMELambda(Lambda)) << getIMELambdaShift(XLen);
+ if (AltFmtA)
+ VType |= 1ULL << getIMEAltFmtAShift(XLen);
+ if (AltFmtB)
+ VType |= 1ULL << getIMEAltFmtBShift(XLen);
+ if (BlockSize16)
+ VType |= 1ULL << getIMEBSShift(XLen);
+ return VType;
+}
+
+uint64_t addIMEVTypeFields(uint64_t VType, unsigned XLen, unsigned Lambda,
+ bool AltFmtA, bool AltFmtB, bool BlockSize16) {
+ return (VType & ~getIMEVTypeFieldsMask(XLen)) |
+ encodeIMEVTypeFields(XLen, Lambda, AltFmtA, AltFmtB, BlockSize16);
+}
+
+unsigned getIMELambdaEncoding(uint64_t VType, unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return (VType >> getIMELambdaShift(XLen)) & 0x7;
+}
+
+std::optional<unsigned> getIMELambda(uint64_t VType, unsigned XLen) {
+ return decodeIMELambda(getIMELambdaEncoding(VType, XLen));
+}
+
+bool isIMEAltFmtA(uint64_t VType, unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return VType & (1ULL << getIMEAltFmtAShift(XLen));
+}
+
+bool isIMEAltFmtB(uint64_t VType, unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return VType & (1ULL << getIMEAltFmtBShift(XLen));
+}
+
+bool isIMEBlockSize16(uint64_t VType, unsigned XLen) {
+ assertValidXLenForIMEVType(XLen);
+ return VType & (1ULL << getIMEBSShift(XLen));
+}
+
std::pair<unsigned, bool> decodeVLMUL(VLMUL VLMul) {
switch (VLMul) {
default:
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index ca2c28c30a30f..e96e2d9d462dc 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1384,6 +1384,7 @@ Experimental extensions
zvfbfa 0.1
zvfofp8min 0.2
zvkgs 0.7
+ zvvmm 0.1
zvzip 0.1
smpmpmt 0.6
svukte 0.3
diff --git a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
index 0302d56e3e3fa..8e0bd36345e70 100644
--- a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
@@ -39,6 +39,57 @@ TEST(RISCVVType, CheckSameRatioLMUL) {
RISCVVType::getSEWLMULRatio(8, RISCVVType::LMUL_F4), 16));
}
+TEST(RISCVVType, IMEVTypeFields) {
+ EXPECT_TRUE(RISCVVType::isValidIMELambda(0));
+ EXPECT_TRUE(RISCVVType::isValidIMELambda(1));
+ EXPECT_TRUE(RISCVVType::isValidIMELambda(64));
+ EXPECT_FALSE(RISCVVType::isValidIMELambda(3));
+ EXPECT_FALSE(RISCVVType::isValidIMELambda(128));
+
+ EXPECT_EQ(0U, RISCVVType::encodeIMELambda(0));
+ EXPECT_EQ(1U, RISCVVType::encodeIMELambda(1));
+ EXPECT_EQ(3U, RISCVVType::encodeIMELambda(4));
+ EXPECT_EQ(7U, RISCVVType::encodeIMELambda(64));
+ EXPECT_EQ(std::nullopt, RISCVVType::decodeIMELambda(0));
+ EXPECT_EQ(std::optional<unsigned>(1), RISCVVType::decodeIMELambda(1));
+ EXPECT_EQ(std::optional<unsigned>(4), RISCVVType::decodeIMELambda(3));
+ EXPECT_EQ(std::optional<unsigned>(64), RISCVVType::decodeIMELambda(7));
+
+ unsigned BaseVType =
+ RISCVVType::encodeVTYPE(RISCVVType::LMUL_1, 32, /*TailAgnostic=*/true,
+ /*MaskAgnostic=*/true);
+
+ uint64_t RV32VType = RISCVVType::addIMEVTypeFields(
+ BaseVType, /*XLen=*/32, /*Lambda=*/4, /*AltFmtA=*/true,
+ /*AltFmtB=*/false, /*BlockSize16=*/true);
+ EXPECT_EQ(0x3a0000d0ULL, RV32VType);
+ EXPECT_EQ(0x7e000000ULL, RISCVVType::getIMEVTypeFieldsMask(32));
+ EXPECT_EQ(3U, RISCVVType::getIMELambdaEncoding(RV32VType, 32));
+ EXPECT_EQ(std::optional<unsigned>(4),
+ RISCVVType::getIMELambda(RV32VType, 32));
+ EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV32VType, 32));
+ EXPECT_FALSE(RISCVVType::isIMEAltFmtB(RV32VType, 32));
+ EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV32VType, 32));
+
+ uint64_t RV64VType = RISCVVType::addIMEVTypeFields(
+ BaseVType, /*XLen=*/64, /*Lambda=*/64, /*AltFmtA=*/true,
+ /*AltFmtB=*/true, /*BlockSize16=*/true);
+ EXPECT_EQ(0x7e000000000000d0ULL, RV64VType);
+ EXPECT_EQ(0x7e00000000000000ULL, RISCVVType::getIMEVTypeFieldsMask(64));
+ EXPECT_EQ(7U, RISCVVType::getIMELambdaEncoding(RV64VType, 64));
+ EXPECT_EQ(std::optional<unsigned>(64),
+ RISCVVType::getIMELambda(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::isIMEAltFmtB(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV64VType, 64));
+
+ uint64_t DynamicLambda = RISCVVType::addIMEVTypeFields(
+ BaseVType, /*XLen=*/64, /*Lambda=*/0, /*AltFmtA=*/false,
+ /*AltFmtB=*/false, /*BlockSize16=*/false);
+ EXPECT_EQ(std::nullopt, RISCVVType::getIMELambda(DynamicLambda, 64));
+ EXPECT_EQ(BaseVType, DynamicLambda);
+}
+
TEST(RISCVTuneFeature, AllTuneFeatures) {
SmallVector<StringRef> AllTuneFeatures;
RISCV::getAllTuneFeatures(AllTuneFeatures);
>From e50e1986c4baa97f36b0b70916b08a70d36f663c Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 24 Apr 2026 20:25:39 +0800
Subject: [PATCH 2/6] [RISCV][Zvvmm] add Zvvmm MC tests
---
llvm/test/MC/RISCV/rvv/zvvmm-invalid.s | 18 +++++++++++++++
llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s | 11 +++++++++
llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s | 11 +++++++++
llvm/test/MC/RISCV/rvv/zvvmm.s | 27 +++++++++++++++++++++++
4 files changed, 67 insertions(+)
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmm-invalid.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
create mode 100644 llvm/test/MC/RISCV/rvv/zvvmm.s
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvmm-invalid.s
new file mode 100644
index 0000000000000..7cccf11b8d1ea
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmm-invalid.s
@@ -0,0 +1,18 @@
+# RUN: not llvm-mc -triple=riscv64 --mattr=+experimental-zvvmm %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+
+vmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vmmacc.vv v8, v4, v20, v0.t
+
+vwmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vwmmacc.vv v8, v4, v20, v0.t
+
+vqmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: vqmmacc.vv v8, v4, v20, v0.t
+
+v8wmmacc.vv v8, v4, v20, v0.t
+# CHECK-ERROR: invalid operand for instruction
+# CHECK-ERROR-LABEL: v8wmmacc.vv v8, v4, v20, v0.t
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
new file mode 100644
index 0000000000000..c284695ffbee8
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
@@ -0,0 +1,11 @@
+# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+experimental-zvvmm %s \
+# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+# SEW=32, LMUL=1, ta, ma, lambda=4, altfmt_A=1, altfmt_B=1.
+li t1, 0x3c0000d0
+vsetvl t0, a0, t1
+# CHECK-INST: vsetvl t0, a0, t1
+# CHECK-ENCODING: [0xd7,0x72,0x65,0x80]
+vmmacc.vv v8, v4, v20
+# CHECK-INST-NEXT: vmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe3]
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
new file mode 100644
index 0000000000000..87ae2065f43cd
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
@@ -0,0 +1,11 @@
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvmm %s \
+# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+# SEW=32, LMUL=1, ta, ma, lambda=4, altfmt_A=1, altfmt_B=1.
+li t1, 0x3c000000000000d0
+vsetvl t0, a0, t1
+# CHECK-INST: vsetvl t0, a0, t1
+# CHECK-ENCODING: [0xd7,0x72,0x65,0x80]
+vmmacc.vv v8, v4, v20
+# CHECK-INST-NEXT: vmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe3]
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm.s b/llvm/test/MC/RISCV/rvv/zvvmm.s
new file mode 100644
index 0000000000000..fad5139fca156
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/zvvmm.s
@@ -0,0 +1,27 @@
+# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvmm %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-zvvmm %s \
+# RUN: | llvm-objdump -d --mattr=+experimental-zvvmm - \
+# RUN: | FileCheck %s --check-prefix=CHECK-INST
+
+vmmacc.vv v8, v4, v20
+# CHECK-INST: vmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe3]
+# CHECK-ERROR: instruction requires the following: 'Zvvmm' (Integer Matrix Multiply-Accumulate){{$}}
+
+vwmmacc.vv v8, v4, v20
+# CHECK-INST: vwmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xe7]
+# CHECK-ERROR: instruction requires the following: 'Zvvmm' (Integer Matrix Multiply-Accumulate){{$}}
+
+vqmmacc.vv v8, v4, v20
+# CHECK-INST: vqmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xeb]
+# CHECK-ERROR: instruction requires the following: 'Zvvmm' (Integer Matrix Multiply-Accumulate){{$}}
+
+v8wmmacc.vv v8, v4, v20
+# CHECK-INST: v8wmmacc.vv v8, v4, v20
+# CHECK-ENCODING: [0x57,0x04,0x42,0xef]
+# CHECK-ERROR: instruction requires the following: 'Zvvmm' (Integer Matrix Multiply-Accumulate){{$}}
>From f400735c446d32e54eade40d78946b098bea6309 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Fri, 24 Apr 2026 21:44:56 +0800
Subject: [PATCH 3/6] fix tests
---
clang/test/Driver/print-supported-extensions-riscv.c | 1 +
llvm/test/CodeGen/RISCV/features-info.ll | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 1a832451ed7bc..83920246d5dad 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -253,6 +253,7 @@
// CHECK-NEXT: zvfbfa 0.1 'Zvfbfa' (Additional BF16 vector compute support)
// CHECK-NEXT: zvfofp8min 0.2 'Zvfofp8min' (Vector OFP8 Converts)
// CHECK-NEXT: zvkgs 0.7 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography)
+// CHECK-NEXT: zvvmm 0.1 'Zvvmm' (Integer Matrix Multiply-Accumulate)
// CHECK-NEXT: zvzip 0.1 'Zvzip' (Vector Reordering Structured Data)
// CHECK-NEXT: smpmpmt 0.6 'Smpmpmt' (PMP-based Memory Types Extension)
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 9f3cfb5a181f2..92e033cb90dc9 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -39,7 +39,8 @@
; CHECK-NEXT: experimental-zvfbfa - 'Zvfbfa' (Additional BF16 vector compute support).
; CHECK-NEXT: experimental-zvfofp8min - 'Zvfofp8min' (Vector OFP8 Converts).
; CHECK-NEXT: experimental-zvkgs - 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography).
-; CHECK-NEXT: experimental-zvzip - 'Zvzip' (Vector Reordering Structured Data).
+; CHECK-NEXT: experimental-zvvmm - 'Zvvmm' (Integer Matrix Multiply-Accumulate).
+; CHECK-NEXT: experimental-zvzip - 'Zvzip' (Vector Reordering Structured Data).
; CHECK-NEXT: f - 'F' (Single-Precision Floating-Point).
; CHECK-NEXT: forced-atomics - Assume that lock-free native-width atomics are available.
; CHECK-NEXT: fusion-add-load - Enable ADD(.UW) + load macrofusion.
>From 751f100dba380cb19fb1e06d45afad3d4b044ad7 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Sat, 25 Apr 2026 13:43:46 +0800
Subject: [PATCH 4/6] Address review: - Do not compare std::optional, just
dereference them - Added experimental-zvvmm notes to RISCVUsage.rst
---
llvm/docs/RISCVUsage.rst | 3 +++
.../TargetParser/RISCVTargetParserTest.cpp | 16 +++++++---------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index bfc7d0afa008b..2c8805f5fe796 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -362,6 +362,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zvzip``
LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__.
+``experimental-zvvmm``
+ LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__.
+
To use an experimental extension from `clang`, you must add `-menable-experimental-extensions` to the command line, and specify the exact version of the experimental extension you are using. To use an experimental extension with LLVM's internal developer tools (e.g. `llc`, `llvm-objdump`, `llvm-mc`), you must prefix the extension name with `experimental-`. Note that you don't need to specify the version with internal tools, and shouldn't include the `experimental-` prefix with `clang`.
Vendor Extensions
diff --git a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
index 8e0bd36345e70..86d6fee28ea24 100644
--- a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
@@ -50,10 +50,10 @@ TEST(RISCVVType, IMEVTypeFields) {
EXPECT_EQ(1U, RISCVVType::encodeIMELambda(1));
EXPECT_EQ(3U, RISCVVType::encodeIMELambda(4));
EXPECT_EQ(7U, RISCVVType::encodeIMELambda(64));
- EXPECT_EQ(std::nullopt, RISCVVType::decodeIMELambda(0));
- EXPECT_EQ(std::optional<unsigned>(1), RISCVVType::decodeIMELambda(1));
- EXPECT_EQ(std::optional<unsigned>(4), RISCVVType::decodeIMELambda(3));
- EXPECT_EQ(std::optional<unsigned>(64), RISCVVType::decodeIMELambda(7));
+ EXPECT_FALSE(RISCVVType::decodeIMELambda(0));
+ EXPECT_EQ(1U, *RISCVVType::decodeIMELambda(1));
+ EXPECT_EQ(4U, *RISCVVType::decodeIMELambda(3));
+ EXPECT_EQ(64U, *RISCVVType::decodeIMELambda(7));
unsigned BaseVType =
RISCVVType::encodeVTYPE(RISCVVType::LMUL_1, 32, /*TailAgnostic=*/true,
@@ -65,8 +65,7 @@ TEST(RISCVVType, IMEVTypeFields) {
EXPECT_EQ(0x3a0000d0ULL, RV32VType);
EXPECT_EQ(0x7e000000ULL, RISCVVType::getIMEVTypeFieldsMask(32));
EXPECT_EQ(3U, RISCVVType::getIMELambdaEncoding(RV32VType, 32));
- EXPECT_EQ(std::optional<unsigned>(4),
- RISCVVType::getIMELambda(RV32VType, 32));
+ EXPECT_EQ(4U, *RISCVVType::getIMELambda(RV32VType, 32));
EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV32VType, 32));
EXPECT_FALSE(RISCVVType::isIMEAltFmtB(RV32VType, 32));
EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV32VType, 32));
@@ -77,8 +76,7 @@ TEST(RISCVVType, IMEVTypeFields) {
EXPECT_EQ(0x7e000000000000d0ULL, RV64VType);
EXPECT_EQ(0x7e00000000000000ULL, RISCVVType::getIMEVTypeFieldsMask(64));
EXPECT_EQ(7U, RISCVVType::getIMELambdaEncoding(RV64VType, 64));
- EXPECT_EQ(std::optional<unsigned>(64),
- RISCVVType::getIMELambda(RV64VType, 64));
+ EXPECT_EQ(64U, *RISCVVType::getIMELambda(RV64VType, 64));
EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV64VType, 64));
EXPECT_TRUE(RISCVVType::isIMEAltFmtB(RV64VType, 64));
EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV64VType, 64));
@@ -86,7 +84,7 @@ TEST(RISCVVType, IMEVTypeFields) {
uint64_t DynamicLambda = RISCVVType::addIMEVTypeFields(
BaseVType, /*XLen=*/64, /*Lambda=*/0, /*AltFmtA=*/false,
/*AltFmtB=*/false, /*BlockSize16=*/false);
- EXPECT_EQ(std::nullopt, RISCVVType::getIMELambda(DynamicLambda, 64));
+ EXPECT_FALSE(RISCVVType::getIMELambda(DynamicLambda, 64));
EXPECT_EQ(BaseVType, DynamicLambda);
}
>From 90a10cdd3b3fc88b66d67c531468c4945c619018 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 27 Apr 2026 18:41:56 +0800
Subject: [PATCH 5/6] Address review: - Remove unneeded tests - Remove Sched
for Zvvmm instructions for now - Reorganize IME encoding helpers to IME
namespace
---
.../llvm/TargetParser/RISCVTargetParser.h | 31 +++----
llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td | 22 ++---
llvm/lib/TargetParser/RISCVTargetParser.cpp | 85 ++++++++++---------
llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s | 11 ---
llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s | 11 ---
.../TargetParser/RISCVTargetParserTest.cpp | 64 +++++++-------
6 files changed, 96 insertions(+), 128 deletions(-)
delete mode 100644 llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
delete mode 100644 llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index d0f4bc0795793..404f40ee22fad 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -129,33 +129,34 @@ LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
-inline static bool isValidIMELambda(unsigned Lambda) {
+namespace IME {
+inline static bool isValidLambda(unsigned Lambda) {
return Lambda == 0 || (isPowerOf2_32(Lambda) && Lambda <= 64);
}
-LLVM_ABI unsigned encodeIMELambda(unsigned Lambda);
+LLVM_ABI unsigned encodeLambda(unsigned Lambda);
-LLVM_ABI std::optional<unsigned> decodeIMELambda(unsigned Encoding);
+LLVM_ABI std::optional<unsigned> decodeLambda(unsigned Encoding);
-LLVM_ABI uint64_t getIMEVTypeFieldsMask(unsigned XLen);
+LLVM_ABI uint64_t getVTypeFieldsMask(unsigned XLen);
-LLVM_ABI uint64_t encodeIMEVTypeFields(unsigned XLen, unsigned Lambda,
- bool AltFmtA, bool AltFmtB,
- bool BlockSize16);
-
-LLVM_ABI uint64_t addIMEVTypeFields(uint64_t VType, unsigned XLen,
- unsigned Lambda, bool AltFmtA, bool AltFmtB,
+LLVM_ABI uint64_t encodeVTypeFields(unsigned XLen, unsigned Lambda,
+ bool AltFmtA, bool AltFmtB,
bool BlockSize16);
-LLVM_ABI unsigned getIMELambdaEncoding(uint64_t VType, unsigned XLen);
+LLVM_ABI uint64_t addVTypeFields(uint64_t VType, unsigned XLen, unsigned Lambda,
+ bool AltFmtA, bool AltFmtB, bool BlockSize16);
+
+LLVM_ABI unsigned getLambdaEncoding(uint64_t VType, unsigned XLen);
-LLVM_ABI std::optional<unsigned> getIMELambda(uint64_t VType, unsigned XLen);
+LLVM_ABI std::optional<unsigned> getLambda(uint64_t VType, unsigned XLen);
-LLVM_ABI bool isIMEAltFmtA(uint64_t VType, unsigned XLen);
+LLVM_ABI bool isAltFmtA(uint64_t VType, unsigned XLen);
-LLVM_ABI bool isIMEAltFmtB(uint64_t VType, unsigned XLen);
+LLVM_ABI bool isAltFmtB(uint64_t VType, unsigned XLen);
-LLVM_ABI bool isIMEBlockSize16(uint64_t VType, unsigned XLen);
+LLVM_ABI bool isBlockSize16(uint64_t VType, unsigned XLen);
+} // namespace IME
inline static VLMUL getVLMUL(unsigned VType) {
unsigned VLMul = VType & 0x7;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
index c4dd6267daa19..d7620bf072ac3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td
@@ -1,4 +1,4 @@
-//===---- RISCVInstrInfoZvvmm.td - 'Zvvmm' instructions -*- tablegen -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -30,20 +30,8 @@ class VIMEMACVV<bits<6> funct6, string opcodestr>
}
let Predicates = [HasStdExtZvvmm] in {
- def VMMACC_VV
- : VIMEMACVV<0b111000, "vmmacc.vv">,
- SchedTernaryMC<"WriteVIMulAddV", "ReadVIMulAddV", "ReadVIMulAddV",
- "ReadVIMulAddV", forceMasked=0>;
- def VWMMACC_VV
- : VIMEMACVV<0b111001, "vwmmacc.vv">,
- SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
- "ReadVIWMulAddV", forceMasked=0>;
- def VQMMACC_VV
- : VIMEMACVV<0b111010, "vqmmacc.vv">,
- SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
- "ReadVIWMulAddV", forceMasked=0>;
- def V8WMMACC_VV
- : VIMEMACVV<0b111011, "v8wmmacc.vv">,
- SchedTernaryMC<"WriteVIWMulAddV", "ReadVIWMulAddV", "ReadVIWMulAddV",
- "ReadVIWMulAddV", forceMasked=0>;
+ def VMMACC_VV : VIMEMACVV<0b111000, "vmmacc.vv">;
+ def VWMMACC_VV : VIMEMACVV<0b111001, "vwmmacc.vv">;
+ def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">;
+ def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">;
} // Predicates = [HasStdExtZvvmm]
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 7fc1b7e38da45..959de5af51254 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -388,93 +388,94 @@ unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt) {
return VTypeI;
}
-static void assertValidXLenForIMEVType(unsigned XLen) {
+namespace IME {
+static void assertValidXLenForVType(unsigned XLen) {
assert((XLen == 32 || XLen == 64) && "Invalid XLEN");
}
-static unsigned getIMELambdaShift(unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
+static unsigned getLambdaShift(unsigned XLen) {
+ assertValidXLenForVType(XLen);
return XLen - 4;
}
-static unsigned getIMEAltFmtAShift(unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
+static unsigned getAltFmtAShift(unsigned XLen) {
+ assertValidXLenForVType(XLen);
return XLen - 5;
}
-static unsigned getIMEAltFmtBShift(unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
+static unsigned getAltFmtBShift(unsigned XLen) {
+ assertValidXLenForVType(XLen);
return XLen - 6;
}
-static unsigned getIMEBSShift(unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
+static unsigned getBSShift(unsigned XLen) {
+ assertValidXLenForVType(XLen);
return XLen - 7;
}
-unsigned encodeIMELambda(unsigned Lambda) {
- assert(isValidIMELambda(Lambda) && "Invalid IME lambda");
+unsigned encodeLambda(unsigned Lambda) {
+ assert(isValidLambda(Lambda) && "Invalid IME lambda");
if (Lambda == 0)
return 0;
return Log2_32(Lambda) + 1;
}
-std::optional<unsigned> decodeIMELambda(unsigned Encoding) {
+std::optional<unsigned> decodeLambda(unsigned Encoding) {
assert(Encoding < 8 && "Invalid IME lambda encoding");
if (Encoding == 0)
return std::nullopt;
return 1U << (Encoding - 1);
}
-uint64_t getIMEVTypeFieldsMask(unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
- return (0x7ULL << getIMELambdaShift(XLen)) |
- (1ULL << getIMEAltFmtAShift(XLen)) |
- (1ULL << getIMEAltFmtBShift(XLen)) | (1ULL << getIMEBSShift(XLen));
+uint64_t getVTypeFieldsMask(unsigned XLen) {
+ assertValidXLenForVType(XLen);
+ return (0x7ULL << getLambdaShift(XLen)) | (1ULL << getAltFmtAShift(XLen)) |
+ (1ULL << getAltFmtBShift(XLen)) | (1ULL << getBSShift(XLen));
}
-uint64_t encodeIMEVTypeFields(unsigned XLen, unsigned Lambda, bool AltFmtA,
- bool AltFmtB, bool BlockSize16) {
- assertValidXLenForIMEVType(XLen);
- uint64_t VType = uint64_t(encodeIMELambda(Lambda)) << getIMELambdaShift(XLen);
+uint64_t encodeVTypeFields(unsigned XLen, unsigned Lambda, bool AltFmtA,
+ bool AltFmtB, bool BlockSize16) {
+ assertValidXLenForVType(XLen);
+ uint64_t VType = uint64_t(encodeLambda(Lambda)) << getLambdaShift(XLen);
if (AltFmtA)
- VType |= 1ULL << getIMEAltFmtAShift(XLen);
+ VType |= 1ULL << getAltFmtAShift(XLen);
if (AltFmtB)
- VType |= 1ULL << getIMEAltFmtBShift(XLen);
+ VType |= 1ULL << getAltFmtBShift(XLen);
if (BlockSize16)
- VType |= 1ULL << getIMEBSShift(XLen);
+ VType |= 1ULL << getBSShift(XLen);
return VType;
}
-uint64_t addIMEVTypeFields(uint64_t VType, unsigned XLen, unsigned Lambda,
- bool AltFmtA, bool AltFmtB, bool BlockSize16) {
- return (VType & ~getIMEVTypeFieldsMask(XLen)) |
- encodeIMEVTypeFields(XLen, Lambda, AltFmtA, AltFmtB, BlockSize16);
+uint64_t addVTypeFields(uint64_t VType, unsigned XLen, unsigned Lambda,
+ bool AltFmtA, bool AltFmtB, bool BlockSize16) {
+ return (VType & ~getVTypeFieldsMask(XLen)) |
+ encodeVTypeFields(XLen, Lambda, AltFmtA, AltFmtB, BlockSize16);
}
-unsigned getIMELambdaEncoding(uint64_t VType, unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
- return (VType >> getIMELambdaShift(XLen)) & 0x7;
+unsigned getLambdaEncoding(uint64_t VType, unsigned XLen) {
+ assertValidXLenForVType(XLen);
+ return (VType >> getLambdaShift(XLen)) & 0x7;
}
-std::optional<unsigned> getIMELambda(uint64_t VType, unsigned XLen) {
- return decodeIMELambda(getIMELambdaEncoding(VType, XLen));
+std::optional<unsigned> getLambda(uint64_t VType, unsigned XLen) {
+ return decodeLambda(getLambdaEncoding(VType, XLen));
}
-bool isIMEAltFmtA(uint64_t VType, unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
- return VType & (1ULL << getIMEAltFmtAShift(XLen));
+bool isAltFmtA(uint64_t VType, unsigned XLen) {
+ assertValidXLenForVType(XLen);
+ return VType & (1ULL << getAltFmtAShift(XLen));
}
-bool isIMEAltFmtB(uint64_t VType, unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
- return VType & (1ULL << getIMEAltFmtBShift(XLen));
+bool isAltFmtB(uint64_t VType, unsigned XLen) {
+ assertValidXLenForVType(XLen);
+ return VType & (1ULL << getAltFmtBShift(XLen));
}
-bool isIMEBlockSize16(uint64_t VType, unsigned XLen) {
- assertValidXLenForIMEVType(XLen);
- return VType & (1ULL << getIMEBSShift(XLen));
+bool isBlockSize16(uint64_t VType, unsigned XLen) {
+ assertValidXLenForVType(XLen);
+ return VType & (1ULL << getBSShift(XLen));
}
+} // namespace IME
std::pair<unsigned, bool> decodeVLMUL(VLMUL VLMul) {
switch (VLMul) {
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
deleted file mode 100644
index c284695ffbee8..0000000000000
--- a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv32.s
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+experimental-zvvmm %s \
-# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
-
-# SEW=32, LMUL=1, ta, ma, lambda=4, altfmt_A=1, altfmt_B=1.
-li t1, 0x3c0000d0
-vsetvl t0, a0, t1
-# CHECK-INST: vsetvl t0, a0, t1
-# CHECK-ENCODING: [0xd7,0x72,0x65,0x80]
-vmmacc.vv v8, v4, v20
-# CHECK-INST-NEXT: vmmacc.vv v8, v4, v20
-# CHECK-ENCODING: [0x57,0x04,0x42,0xe3]
diff --git a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s b/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
deleted file mode 100644
index 87ae2065f43cd..0000000000000
--- a/llvm/test/MC/RISCV/rvv/zvvmm-vtype-rv64.s
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvmm %s \
-# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
-
-# SEW=32, LMUL=1, ta, ma, lambda=4, altfmt_A=1, altfmt_B=1.
-li t1, 0x3c000000000000d0
-vsetvl t0, a0, t1
-# CHECK-INST: vsetvl t0, a0, t1
-# CHECK-ENCODING: [0xd7,0x72,0x65,0x80]
-vmmacc.vv v8, v4, v20
-# CHECK-INST-NEXT: vmmacc.vv v8, v4, v20
-# CHECK-ENCODING: [0x57,0x04,0x42,0xe3]
diff --git a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
index 86d6fee28ea24..7ecdf4300f930 100644
--- a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
@@ -40,51 +40,51 @@ TEST(RISCVVType, CheckSameRatioLMUL) {
}
TEST(RISCVVType, IMEVTypeFields) {
- EXPECT_TRUE(RISCVVType::isValidIMELambda(0));
- EXPECT_TRUE(RISCVVType::isValidIMELambda(1));
- EXPECT_TRUE(RISCVVType::isValidIMELambda(64));
- EXPECT_FALSE(RISCVVType::isValidIMELambda(3));
- EXPECT_FALSE(RISCVVType::isValidIMELambda(128));
-
- EXPECT_EQ(0U, RISCVVType::encodeIMELambda(0));
- EXPECT_EQ(1U, RISCVVType::encodeIMELambda(1));
- EXPECT_EQ(3U, RISCVVType::encodeIMELambda(4));
- EXPECT_EQ(7U, RISCVVType::encodeIMELambda(64));
- EXPECT_FALSE(RISCVVType::decodeIMELambda(0));
- EXPECT_EQ(1U, *RISCVVType::decodeIMELambda(1));
- EXPECT_EQ(4U, *RISCVVType::decodeIMELambda(3));
- EXPECT_EQ(64U, *RISCVVType::decodeIMELambda(7));
+ EXPECT_TRUE(RISCVVType::IME::isValidLambda(0));
+ EXPECT_TRUE(RISCVVType::IME::isValidLambda(1));
+ EXPECT_TRUE(RISCVVType::IME::isValidLambda(64));
+ EXPECT_FALSE(RISCVVType::IME::isValidLambda(3));
+ EXPECT_FALSE(RISCVVType::IME::isValidLambda(128));
+
+ EXPECT_EQ(0U, RISCVVType::IME::encodeLambda(0));
+ EXPECT_EQ(1U, RISCVVType::IME::encodeLambda(1));
+ EXPECT_EQ(3U, RISCVVType::IME::encodeLambda(4));
+ EXPECT_EQ(7U, RISCVVType::IME::encodeLambda(64));
+ EXPECT_FALSE(RISCVVType::IME::decodeLambda(0));
+ EXPECT_EQ(1U, *RISCVVType::IME::decodeLambda(1));
+ EXPECT_EQ(4U, *RISCVVType::IME::decodeLambda(3));
+ EXPECT_EQ(64U, *RISCVVType::IME::decodeLambda(7));
unsigned BaseVType =
RISCVVType::encodeVTYPE(RISCVVType::LMUL_1, 32, /*TailAgnostic=*/true,
/*MaskAgnostic=*/true);
- uint64_t RV32VType = RISCVVType::addIMEVTypeFields(
+ uint64_t RV32VType = RISCVVType::IME::addVTypeFields(
BaseVType, /*XLen=*/32, /*Lambda=*/4, /*AltFmtA=*/true,
/*AltFmtB=*/false, /*BlockSize16=*/true);
EXPECT_EQ(0x3a0000d0ULL, RV32VType);
- EXPECT_EQ(0x7e000000ULL, RISCVVType::getIMEVTypeFieldsMask(32));
- EXPECT_EQ(3U, RISCVVType::getIMELambdaEncoding(RV32VType, 32));
- EXPECT_EQ(4U, *RISCVVType::getIMELambda(RV32VType, 32));
- EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV32VType, 32));
- EXPECT_FALSE(RISCVVType::isIMEAltFmtB(RV32VType, 32));
- EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV32VType, 32));
-
- uint64_t RV64VType = RISCVVType::addIMEVTypeFields(
+ EXPECT_EQ(0x7e000000ULL, RISCVVType::IME::getVTypeFieldsMask(32));
+ EXPECT_EQ(3U, RISCVVType::IME::getLambdaEncoding(RV32VType, 32));
+ EXPECT_EQ(4U, *RISCVVType::IME::getLambda(RV32VType, 32));
+ EXPECT_TRUE(RISCVVType::IME::isAltFmtA(RV32VType, 32));
+ EXPECT_FALSE(RISCVVType::IME::isAltFmtB(RV32VType, 32));
+ EXPECT_TRUE(RISCVVType::IME::isBlockSize16(RV32VType, 32));
+
+ uint64_t RV64VType = RISCVVType::IME::addVTypeFields(
BaseVType, /*XLen=*/64, /*Lambda=*/64, /*AltFmtA=*/true,
/*AltFmtB=*/true, /*BlockSize16=*/true);
EXPECT_EQ(0x7e000000000000d0ULL, RV64VType);
- EXPECT_EQ(0x7e00000000000000ULL, RISCVVType::getIMEVTypeFieldsMask(64));
- EXPECT_EQ(7U, RISCVVType::getIMELambdaEncoding(RV64VType, 64));
- EXPECT_EQ(64U, *RISCVVType::getIMELambda(RV64VType, 64));
- EXPECT_TRUE(RISCVVType::isIMEAltFmtA(RV64VType, 64));
- EXPECT_TRUE(RISCVVType::isIMEAltFmtB(RV64VType, 64));
- EXPECT_TRUE(RISCVVType::isIMEBlockSize16(RV64VType, 64));
-
- uint64_t DynamicLambda = RISCVVType::addIMEVTypeFields(
+ EXPECT_EQ(0x7e00000000000000ULL, RISCVVType::IME::getVTypeFieldsMask(64));
+ EXPECT_EQ(7U, RISCVVType::IME::getLambdaEncoding(RV64VType, 64));
+ EXPECT_EQ(64U, *RISCVVType::IME::getLambda(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::IME::isAltFmtA(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::IME::isAltFmtB(RV64VType, 64));
+ EXPECT_TRUE(RISCVVType::IME::isBlockSize16(RV64VType, 64));
+
+ uint64_t DynamicLambda = RISCVVType::IME::addVTypeFields(
BaseVType, /*XLen=*/64, /*Lambda=*/0, /*AltFmtA=*/false,
/*AltFmtB=*/false, /*BlockSize16=*/false);
- EXPECT_FALSE(RISCVVType::getIMELambda(DynamicLambda, 64));
+ EXPECT_FALSE(RISCVVType::IME::getLambda(DynamicLambda, 64));
EXPECT_EQ(BaseVType, DynamicLambda);
}
>From c7df3acd78ba2b9fd13e74214e16ada96e8ed7b7 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Mon, 27 Apr 2026 19:03:37 +0800
Subject: [PATCH 6/6] Address review: - Removed optional header - Added release
notes
---
llvm/docs/ReleaseNotes.md | 1 +
llvm/include/llvm/TargetParser/RISCVTargetParser.h | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 740c88899e659..ed08329950257 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -192,6 +192,7 @@ Changes to the RISC-V Backend
Reordering Structured Data) extension.
* `-mcpu=sifive-x160` and `-mcpu=sifive-x180` were added.
* Support for the experimental `XRivosVisni` vendor extension has been removed.
+* Adds experimental assembler support for the 'Zvvmm` (RISC-V Integer Matrix Multiply-Accumulate) extension.
Changes to the WebAssembly Backend
----------------------------------
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index 404f40ee22fad..a3ff841a88381 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -19,7 +19,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include <optional>
namespace llvm {
More information about the cfe-commits
mailing list