https://github.com/imkiva updated https://github.com/llvm/llvm-project/pull/196486
>From 2f8fb98529fb12db614abc780434b1a558bd9364 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Wed, 6 May 2026 13:23:19 +0800 Subject: [PATCH 1/7] [RISCV][MC] add experimental `Zvvfmm` support --- llvm/docs/RISCVUsage.rst | 3 ++ llvm/docs/ReleaseNotes.md | 1 + llvm/lib/Target/RISCV/RISCVFeatures.td | 10 ++++++- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +- ...nstrInfoZvvmm.td => RISCVInstrInfoZvvm.td} | 28 ++++++++++++++++--- llvm/test/CodeGen/RISCV/features-info.ll | 1 + llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 18 ++++++++++++ llvm/test/MC/RISCV/rvv/zvvfmm.s | 27 ++++++++++++++++++ .../TargetParser/RISCVISAInfoTest.cpp | 1 + 9 files changed, 85 insertions(+), 6 deletions(-) rename llvm/lib/Target/RISCV/{RISCVInstrInfoZvvmm.td => RISCVInstrInfoZvvm.td} (61%) create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm.s diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 2b68827e7b136..4824dcd3c99e5 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -363,6 +363,9 @@ The primary goal of experimental support is to assist in the process of ratifica ``experimental-zvzip`` LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__. +``experimental-zvvfmm`` + LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/fa5575203a2dc2e086bc4edc9de7fd9439816488/src/integrated-matrix.adoc>`__. + ``experimental-zvvmm`` LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__. diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index ec613d64e20a3..57e7812284991 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -203,6 +203,7 @@ Makes programs 10x faster by doing Special New Thing. * Support for the experimental `XRivosVisni` vendor extension has been removed. * Adds experimental assembler support for the 'Zvvmm` (RISC-V Integer Matrix Multiply-Accumulate) extension. * Adds support for 'Ziccid' (Instruction/Data Coherence and Consistency) extension. +* Adds experimental assembler support for the 'Zvvfmm` (RISC-V Floating-Point Matrix Multiply-Accumulate) extension. ### Changes to the WebAssembly Backend diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index a92fb63e3c3cd..852311579d1c2 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -897,6 +897,15 @@ def HasStdExtZvvmm : Predicate<"Subtarget->hasStdExtZvvmm()">, AssemblerPredicate<(all_of FeatureStdExtZvvmm), "'Zvvmm' (Integer Matrix Multiply-Accumulate)">; +// Integrated Matrix Extension floating-point matrix multiply-accumulate +def FeatureStdExtZvvfmm + : RISCVExperimentalExtension<0, 1, + "Floating-Point Matrix Multiply-Accumulate", + [FeatureStdExtZve32f]>; +def HasStdExtZvvfmm : Predicate<"Subtarget->hasStdExtZvvfmm()">, + AssemblerPredicate<(all_of FeatureStdExtZvvfmm), + "'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate)">; + // Vector instruction predicates def HasVInstructions : Predicate<"Subtarget->hasVInstructions()">, @@ -2076,4 +2085,3 @@ def TuneSiFive7 : SubtargetFeature<"sifive7", "RISCVProcFamily", "SiFive7", def TuneVentanaVeyron : SubtargetFeature<"ventana-veyron", "RISCVProcFamily", "VentanaVeyron", "Ventana Veyron-Series processors">; - diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 3295d18a2d352..541bf302bf8e5 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -2356,7 +2356,7 @@ include "RISCVInstrInfoZvk.td" include "RISCVInstrInfoZvdot4a8i.td" include "RISCVInstrInfoZvfofp8min.td" include "RISCVInstrInfoZvzip.td" -include "RISCVInstrInfoZvvmm.td" +include "RISCVInstrInfoZvvm.td" // Packed SIMD include "RISCVInstrInfoP.td" diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td similarity index 61% rename from llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td rename to llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td index d7620bf072ac3..1334eda8e7b44 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvmm.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td @@ -6,10 +6,9 @@ // //===----------------------------------------------------------------------===// // -// This file describes the RISC-V instructions from the standard 'Zvvmm' -// extension for integer matrix multiply-accumulate. -// This version is still experimental as the 'Zvvmm' extension hasn't been -// ratified yet. +// This file describes the RISC-V instructions from the standard 'Zvvm' family +// of Integrated Matrix extensions. +// These extensions are still experimental as they haven't been ratified yet. // //===----------------------------------------------------------------------===// @@ -35,3 +34,24 @@ let Predicates = [HasStdExtZvvmm] in { def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">; def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">; } // Predicates = [HasStdExtZvvmm] + +class VFMEMACVV<bits<6> funct6, string opcodestr> + : RVInstVV<funct6, OPFVV, (outs VR:$vd_wb), + (ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr, + "$vd, $vs1, $vs2"> { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = "$vd = $vd_wb"; + let Uses = [FRM, VL, VTYPE]; + let mayRaiseFPException = true; + let vm = 1; + let VMConstraint = false; +} + +let Predicates = [HasStdExtZvvfmm] in { + def VFMMACC_VV : VFMEMACVV<0b010100, "vfmmacc.vv">; + def VFWMMACC_VV : VFMEMACVV<0b010101, "vfwmmacc.vv">; + def VFQMMACC_VV : VFMEMACVV<0b010110, "vfqmmacc.vv">; + def VF8WMMACC_VV : VFMEMACVV<0b010111, "vf8wmmacc.vv">; +} // Predicates = [HasStdExtZvvfmm] diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll index d4b920c08a096..96f193a2633f5 100644 --- a/llvm/test/CodeGen/RISCV/features-info.ll +++ b/llvm/test/CodeGen/RISCV/features-info.ll @@ -39,6 +39,7 @@ ; CHECK-NEXT: experimental-zvfbfa - 'Zvfbfa' (Additional BF16 vector compute support). ; CHECK-NEXT: experimental-zvfofp8min - 'Zvfofp8min' (Vector OFP8 Converts). ; CHECK-NEXT: experimental-zvkgs - 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography). +; CHECK-NEXT: experimental-zvvfmm - 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate). ; CHECK-NEXT: experimental-zvvmm - 'Zvvmm' (Integer Matrix Multiply-Accumulate). ; CHECK-NEXT: experimental-zvzip - 'Zvzip' (Vector Reordering Structured Data). ; CHECK-NEXT: f - 'F' (Single-Precision Floating-Point). diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s new file mode 100644 index 0000000000000..7f00b757fa87b --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s @@ -0,0 +1,18 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+experimental-zvvfmm %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vfmmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t + +vfwmmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v0.t + +vfqmmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v0.t + +vf8wmmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v0.t diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm.s b/llvm/test/MC/RISCV/rvv/zvvfmm.s new file mode 100644 index 0000000000000..3b398e88f7f7b --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvvfmm.s @@ -0,0 +1,27 @@ +# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-zvvfmm %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR +# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvfmm %s \ +# RUN: | llvm-objdump -d --mattr=+experimental-zvvfmm - \ +# RUN: | FileCheck %s --check-prefix=CHECK-INST + +vfmmacc.vv v8, v4, v20 +# CHECK-INST: vfmmacc.vv v8, v4, v20 +# CHECK-ENCODING: [0x57,0x14,0x42,0x53] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vfwmmacc.vv v8, v4, v20 +# CHECK-INST: vfwmmacc.vv v8, v4, v20 +# CHECK-ENCODING: [0x57,0x14,0x42,0x57] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vfqmmacc.vv v8, v4, v20 +# CHECK-INST: vfqmmacc.vv v8, v4, v20 +# CHECK-ENCODING: [0x57,0x14,0x42,0x5b] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vf8wmmacc.vv v8, v4, v20 +# CHECK-INST: vf8wmmacc.vv v8, v4, v20 +# CHECK-ENCODING: [0x57,0x14,0x42,0x5f] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index d28066d423b77..cd0dcf98f50de 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -1385,6 +1385,7 @@ Experimental extensions zvfbfa 0.1 zvfofp8min 0.2 zvkgs 0.7 + zvvfmm 0.1 zvvmm 0.1 zvzip 0.1 smpmpmt 0.6 >From e139e82c3125fb5be29aa498059f5d7c05bdd4c4 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Wed, 6 May 2026 22:49:34 +0800 Subject: [PATCH 2/7] [RISCV][MC] add basic microscaling instructions --- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 21 ++++++ .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 11 ++++ .../RISCV/MCTargetDesc/RISCVInstPrinter.h | 2 + llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 66 +++++++++++++++++-- llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 58 +++++++++++++++- llvm/test/MC/RISCV/rvv/zvvfmm.s | 30 +++++++++ 6 files changed, 178 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index cbf3d0f518ac8..ddee58bb973d2 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -206,6 +206,7 @@ class RISCVAsmParser : public MCTargetAsmParser { ParseStatus parseJALOffset(OperandVector &Operands); ParseStatus parseVTypeI(OperandVector &Operands); ParseStatus parseMaskReg(OperandVector &Operands); + ParseStatus parseVScaleReg(OperandVector &Operands); ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands); ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands); ParseStatus parseGPRAsFPR(OperandVector &Operands); @@ -2522,6 +2523,26 @@ ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) { return ParseStatus::Success; } +ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) { + if (getLexer().isNot(AsmToken::Identifier)) + return ParseStatus::NoMatch; + + StringRef Name = getLexer().getTok().getIdentifier(); + if (!Name.consume_back(".scale")) + return Error(getLoc(), "expected '.scale' suffix"); + MCRegister Reg = matchRegisterNameHelper(Name); + + if (!Reg) + return ParseStatus::NoMatch; + if (Reg != RISCV::V0) + return ParseStatus::NoMatch; + SMLoc S = getLoc(); + SMLoc E = getTok().getEndLoc(); + getLexer().Lex(); + Operands.push_back(RISCVOperand::createReg(Reg, S, E)); + return ParseStatus::Success; +} + ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) { if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF)) return ParseStatus::NoMatch; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index b381b8f7147fc..e2416f832aecc 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -341,6 +341,17 @@ void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, O << ".t"; } +void RISCVInstPrinter::printVScaleReg(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + + assert(MO.isReg() && "printVScaleReg can only print register operands"); + O << ", "; + printRegName(O, MO.getReg()); + O << ".scale"; +} + void RISCVInstPrinter::printImm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h index 17469bd87e34e..fb0598faff2be 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h @@ -52,6 +52,8 @@ class RISCVInstPrinter : public MCInstPrinter { const MCSubtargetInfo &STI, raw_ostream &O); void printVMaskReg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); + void printVScaleReg(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); void printImm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); void printRegList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td index 1334eda8e7b44..5425ce391e8aa 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td @@ -16,6 +16,24 @@ // Instructions //===----------------------------------------------------------------------===// +def VScaleAsmOperand : AsmOperandClass { + let Name = "RVVScaleRegOpOperand"; + let RenderMethod = "addRegOperands"; + let PredicateMethod = "isV0Reg"; + let ParserMethod = "parseVScaleReg"; + let DiagnosticType = "InvalidVScaleRegister"; + let DiagnosticString = "operand must be v0.scale"; +} + +// An always present v0.scale operand encoded with vm=0. Classes that use this +// must set the vm field in RVInstV* to 0. +def VScaleOp : RegisterOperand<VMV0> { + let ParserMatchClass = VScaleAsmOperand; + let PrintMethod = "printVScaleReg"; + let EncoderMethod = "getVMaskReg"; + let DecoderMethod = "decodeVMaskReg"; +} + class VIMEMACVV<bits<6> funct6, string opcodestr> : RVInstVV<funct6, OPIVV, (outs VR:$vd_wb), (ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr, @@ -28,13 +46,6 @@ class VIMEMACVV<bits<6> funct6, string opcodestr> let VMConstraint = false; } -let Predicates = [HasStdExtZvvmm] in { - def VMMACC_VV : VIMEMACVV<0b111000, "vmmacc.vv">; - def VWMMACC_VV : VIMEMACVV<0b111001, "vwmmacc.vv">; - def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">; - def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">; -} // Predicates = [HasStdExtZvvmm] - class VFMEMACVV<bits<6> funct6, string opcodestr> : RVInstVV<funct6, OPFVV, (outs VR:$vd_wb), (ins VR:$vd, VR:$vs1, VR:$vs2), opcodestr, @@ -49,9 +60,50 @@ class VFMEMACVV<bits<6> funct6, string opcodestr> let VMConstraint = false; } +class VFMEMACScaleVV<bits<6> funct6, string opcodestr> + : RVInstVV<funct6, OPFVV, (outs VR:$vd_wb), + (ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr, + "$vd, $vs1, $vs2$vm"> { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = "$vd = $vd_wb"; + let Uses = [FRM, VL, VTYPE]; + let mayRaiseFPException = true; + let vm = 0; + let VMConstraint = false; +} + +class VIFMEMACScaleVV<bits<6> funct6, string opcodestr> + : RVInstVV<funct6, OPIVV, (outs VR:$vd_wb), + (ins VR:$vd, VR:$vs1, VR:$vs2, VScaleOp:$vm), opcodestr, + "$vd, $vs1, $vs2$vm"> { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = "$vd = $vd_wb"; + let Uses = [FRM, VL, VTYPE]; + let mayRaiseFPException = true; + let vm = 0; + let VMConstraint = false; +} + +let Predicates = [HasStdExtZvvmm] in { + def VMMACC_VV : VIMEMACVV<0b111000, "vmmacc.vv">; + def VWMMACC_VV : VIMEMACVV<0b111001, "vwmmacc.vv">; + def VQMMACC_VV : VIMEMACVV<0b111010, "vqmmacc.vv">; + def V8WMMACC_VV : VIMEMACVV<0b111011, "v8wmmacc.vv">; +} // Predicates = [HasStdExtZvvmm] + let Predicates = [HasStdExtZvvfmm] in { def VFMMACC_VV : VFMEMACVV<0b010100, "vfmmacc.vv">; def VFWMMACC_VV : VFMEMACVV<0b010101, "vfwmmacc.vv">; def VFQMMACC_VV : VFMEMACVV<0b010110, "vfqmmacc.vv">; def VF8WMMACC_VV : VFMEMACVV<0b010111, "vf8wmmacc.vv">; + def VFWMMACC_VV_SCALE : VFMEMACScaleVV<0b010101, "vfwmmacc.vv">; + def VFQMMACC_VV_SCALE : VFMEMACScaleVV<0b010110, "vfqmmacc.vv">; + def VF8WMMACC_VV_SCALE : VFMEMACScaleVV<0b010111, "vf8wmmacc.vv">; + def VFWIMMACC_VV : VIFMEMACScaleVV<0b111001, "vfwimmacc.vv">; + def VFQIMMACC_VV : VIFMEMACScaleVV<0b111010, "vfqimmacc.vv">; + def VF8WIMMACC_VV : VIFMEMACScaleVV<0b111011, "vf8wimmacc.vv">; } // Predicates = [HasStdExtZvvfmm] diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s index 7f00b757fa87b..b510195591bf5 100644 --- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s @@ -5,14 +5,66 @@ vfmmacc.vv v8, v4, v20, v0.t # CHECK-ERROR: invalid operand for instruction # CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t -vfwmmacc.vv v8, v4, v20, v0.t +vfmmacc.vv v8, v4, v20, v0.scale # CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.scale + +vfwmmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: expected '.scale' suffix # CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v0.t +vfwmmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vfwmmacc.vv v8, v4, v20, v1.scale + vfqmmacc.vv v8, v4, v20, v0.t -# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR: expected '.scale' suffix # CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v0.t +vfqmmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v4, v20, v1.scale + vf8wmmacc.vv v8, v4, v20, v0.t -# CHECK-ERROR: invalid operand for instruction +# CHECK-ERROR: expected '.scale' suffix # CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v0.t + +vf8wmmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v1.scale + +vfwimmacc.vv v8, v4, v20 +# CHECK-ERROR: too few operands for instruction +# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20 + +vfwimmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: expected '.scale' suffix +# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v0.t + +vfwimmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v1.scale + +vfqimmacc.vv v8, v4, v20 +# CHECK-ERROR: too few operands for instruction +# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20 + +vfqimmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: expected '.scale' suffix +# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v0.t + +vfqimmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v1.scale + +vf8wimmacc.vv v8, v4, v20 +# CHECK-ERROR: too few operands for instruction +# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20 + +vf8wimmacc.vv v8, v4, v20, v0.t +# CHECK-ERROR: expected '.scale' suffix +# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v0.t + +vf8wimmacc.vv v8, v4, v20, v1.scale +# CHECK-ERROR: operand must be v0.scale +# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v1.scale diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm.s b/llvm/test/MC/RISCV/rvv/zvvfmm.s index 3b398e88f7f7b..4c6a60d5b3fff 100644 --- a/llvm/test/MC/RISCV/rvv/zvvfmm.s +++ b/llvm/test/MC/RISCV/rvv/zvvfmm.s @@ -16,12 +16,42 @@ vfwmmacc.vv v8, v4, v20 # CHECK-ENCODING: [0x57,0x14,0x42,0x57] # CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} +vfwmmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vfwmmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x14,0x42,0x55] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + vfqmmacc.vv v8, v4, v20 # CHECK-INST: vfqmmacc.vv v8, v4, v20 # CHECK-ENCODING: [0x57,0x14,0x42,0x5b] # CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} +vfqmmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vfqmmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x14,0x42,0x59] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + vf8wmmacc.vv v8, v4, v20 # CHECK-INST: vf8wmmacc.vv v8, v4, v20 # CHECK-ENCODING: [0x57,0x14,0x42,0x5f] # CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vf8wmmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vf8wmmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x14,0x42,0x5d] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vfwimmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vfwimmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x04,0x42,0xe5] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vfqimmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vfqimmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x04,0x42,0xe9] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} + +vf8wimmacc.vv v8, v4, v20, v0.scale +# CHECK-INST: vf8wimmacc.vv v8, v4, v20, v0.scale +# CHECK-ENCODING: [0x57,0x04,0x42,0xed] +# CHECK-ERROR: instruction requires the following: 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate){{$}} >From f7640e8f1bdbf1fd2fd9b9871c4ba782deb7d8c2 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Fri, 8 May 2026 15:16:24 +0800 Subject: [PATCH 3/7] [RISCV][MC] check if v0.scale overlaps vs1, vs2, vd --- llvm/docs/RISCVUsage.rst | 2 +- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 38 +++++++++++++++++++ llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 24 ++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 4824dcd3c99e5..7df6ef78c27ac 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -364,7 +364,7 @@ The primary goal of experimental support is to assist in the process of ratifica LLVM implements the `0.1 draft specification <https://github.com/ved-rivos/riscv-isa-manual/blob/zvzip/src/zvzip.adoc>`__. ``experimental-zvvfmm`` - LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/fa5575203a2dc2e086bc4edc9de7fd9439816488/src/integrated-matrix.adoc>`__. + LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__. ``experimental-zvvmm`` LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__. diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index ddee58bb973d2..1b2742c76da05 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -3924,6 +3924,20 @@ unsigned getLMULFromVectorRegister(MCRegister Reg) { return 1; } +static bool isZvvfmmScaleOpcode(unsigned Opcode) { + switch (Opcode) { + case RISCV::VFWMMACC_VV_SCALE: + case RISCV::VFQMMACC_VV_SCALE: + case RISCV::VF8WMMACC_VV_SCALE: + case RISCV::VFWIMMACC_VV: + case RISCV::VFQIMMACC_VV: + case RISCV::VF8WIMMACC_VV: + return true; + default: + return false; + } +} + bool RISCVAsmParser::validateInstruction(MCInst &Inst, OperandVector &Operands) { unsigned Opcode = Inst.getOpcode(); @@ -3960,6 +3974,30 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, } } + if (isZvvfmmScaleOpcode(Opcode)) { + auto CheckOperandDoesNotOverlapV0 = [&](int OperandIdx, + unsigned ParsedIdx) { + if (Inst.getOperand(OperandIdx).getReg() == RISCV::V0) + return Error(Operands[ParsedIdx]->getStartLoc(), + "vd, vs1, and vs2 cannot overlap v0.scale"); + return false; + }; + + int DestIdx = + RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd); + int VS1Idx = + RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1); + int VS2Idx = + RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2); + assert(DestIdx >= 0 && VS1Idx >= 0 && VS2Idx >= 0 && + "Unexpected Zvvfmm scaled operand list"); + + if (CheckOperandDoesNotOverlapV0(DestIdx, 1) || + CheckOperandDoesNotOverlapV0(VS1Idx, 2) || + CheckOperandDoesNotOverlapV0(VS2Idx, 3)) + return true; + } + const MCInstrDesc &MCID = MII.get(Opcode); if (!(MCID.TSFlags & RISCVII::RVVConstraintMask)) return false; diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s index b510195591bf5..8f5f10ef2d6bd 100644 --- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s @@ -33,6 +33,18 @@ vf8wmmacc.vv v8, v4, v20, v1.scale # CHECK-ERROR: operand must be v0.scale # CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v20, v1.scale +vfwmmacc.vv v0, v4, v20, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vfwmmacc.vv v0, v4, v20, v0.scale + +vfqmmacc.vv v8, v0, v20, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vfqmmacc.vv v8, v0, v20, v0.scale + +vf8wmmacc.vv v8, v4, v0, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vf8wmmacc.vv v8, v4, v0, v0.scale + vfwimmacc.vv v8, v4, v20 # CHECK-ERROR: too few operands for instruction # CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20 @@ -45,6 +57,10 @@ vfwimmacc.vv v8, v4, v20, v1.scale # CHECK-ERROR: operand must be v0.scale # CHECK-ERROR-LABEL: vfwimmacc.vv v8, v4, v20, v1.scale +vfwimmacc.vv v0, v4, v20, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vfwimmacc.vv v0, v4, v20, v0.scale + vfqimmacc.vv v8, v4, v20 # CHECK-ERROR: too few operands for instruction # CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20 @@ -57,6 +73,10 @@ vfqimmacc.vv v8, v4, v20, v1.scale # CHECK-ERROR: operand must be v0.scale # CHECK-ERROR-LABEL: vfqimmacc.vv v8, v4, v20, v1.scale +vfqimmacc.vv v8, v0, v20, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vfqimmacc.vv v8, v0, v20, v0.scale + vf8wimmacc.vv v8, v4, v20 # CHECK-ERROR: too few operands for instruction # CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20 @@ -68,3 +88,7 @@ vf8wimmacc.vv v8, v4, v20, v0.t vf8wimmacc.vv v8, v4, v20, v1.scale # CHECK-ERROR: operand must be v0.scale # CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v20, v1.scale + +vf8wimmacc.vv v8, v4, v0, v0.scale +# CHECK-ERROR: vd, vs1, and vs2 cannot overlap v0.scale +# CHECK-ERROR-LABEL: vf8wimmacc.vv v8, v4, v0, v0.scale >From 9a2f80a4ef8c6980a78ac46568b9cf1cafa4ddc1 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Fri, 8 May 2026 15:18:41 +0800 Subject: [PATCH 4/7] Update docs --- llvm/docs/RISCVUsage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 7df6ef78c27ac..71d91f73383b5 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -367,7 +367,7 @@ The primary goal of experimental support is to assist in the process of ratifica LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__. ``experimental-zvvmm`` - LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/blob/d2e64b4922f5c2c416761f3c7c997d4f0cf814d9/src/integrated-matrix.adoc>`__. + LLVM implements the `0.1 draft specification <https://github.com/riscv/integrated-matrix-extension/releases/tag/riscv-isa-release-fa55752-2026-05-04>`__. To use an experimental extension from `clang`, you must add `-menable-experimental-extensions` to the command line, and specify the exact version of the experimental extension you are using. To use an experimental extension with LLVM's internal developer tools (e.g. `llc`, `llvm-objdump`, `llvm-mc`), you must prefix the extension name with `experimental-`. Note that you don't need to specify the version with internal tools, and shouldn't include the `experimental-` prefix with `clang`. >From 1f29305e7eb9603facaf6d23ff181e7f79891441 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Fri, 8 May 2026 16:24:55 +0800 Subject: [PATCH 5/7] Update tests --- clang/test/Driver/print-supported-extensions-riscv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index d0a773f8f43d8..82ef3e54dab29 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -254,6 +254,7 @@ // CHECK-NEXT: zvfbfa 0.1 'Zvfbfa' (Additional BF16 vector compute support) // CHECK-NEXT: zvfofp8min 0.2 'Zvfofp8min' (Vector OFP8 Converts) // CHECK-NEXT: zvkgs 0.7 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography) +// CHECK-NEXT: zvvfmm 0.1 'Zvvfmm' (Floating-Point Matrix Multiply-Accumulate) // CHECK-NEXT: zvvmm 0.1 'Zvvmm' (Integer Matrix Multiply-Accumulate) // CHECK-NEXT: zvzip 0.1 'Zvzip' (Vector Reordering Structured Data) // CHECK-NEXT: smpmpmt 0.6 'Smpmpmt' (PMP-based Memory Types Extension) >From 3382f6308efa3af75bb58cd9f7072adba1843924 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Fri, 8 May 2026 16:50:59 +0800 Subject: [PATCH 6/7] Update comments --- llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td index 5425ce391e8aa..0a358ba9ba0bb 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvvm.td @@ -103,6 +103,10 @@ let Predicates = [HasStdExtZvvfmm] in { def VFWMMACC_VV_SCALE : VFMEMACScaleVV<0b010101, "vfwmmacc.vv">; def VFQMMACC_VV_SCALE : VFMEMACScaleVV<0b010110, "vfqmmacc.vv">; def VF8WMMACC_VV_SCALE : VFMEMACScaleVV<0b010111, "vf8wmmacc.vv">; + // FIXME: The integer-input MX forms should be gated by the + // Zvvxi*/Zvvxni* microscaling extensions once LLVM models those + // individual extension names. They are temporarily enabled under + // experimental-zvvfmm for MC bring-up. def VFWIMMACC_VV : VIFMEMACScaleVV<0b111001, "vfwimmacc.vv">; def VFQIMMACC_VV : VIFMEMACScaleVV<0b111010, "vfqimmacc.vv">; def VF8WIMMACC_VV : VIFMEMACScaleVV<0b111011, "vf8wimmacc.vv">; >From c4085a48cb8d94ada6524d2ab56f040012f1b3f0 Mon Sep 17 00:00:00 2001 From: imkiva <[email protected]> Date: Fri, 8 May 2026 16:56:35 +0800 Subject: [PATCH 7/7] More tests --- llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s | 9 +++++++++ llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s | 1 + 2 files changed, 10 insertions(+) create mode 100644 llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s new file mode 100644 index 0000000000000..239153b62c233 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid-encoding.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-zvvfmm %s \ +# RUN: | llvm-objdump -d --mattr=+experimental-zvvfmm - \ +# RUN: | FileCheck %s + +# vm=0 is reserved for non-widening vfmmacc.vv, so this raw encoding must not +# decode as a scaled vfmmacc form. +.insn 0x4, 0x51421457 +# CHECK: <unknown> +# CHECK-NOT: vfmmacc.vv diff --git a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s index 8f5f10ef2d6bd..ccb1e7ebcd12d 100644 --- a/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvvfmm-invalid.s @@ -5,6 +5,7 @@ vfmmacc.vv v8, v4, v20, v0.t # CHECK-ERROR: invalid operand for instruction # CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.t +# vm=0 is reserved for non-widening vfmmacc.vv. vfmmacc.vv v8, v4, v20, v0.scale # CHECK-ERROR: invalid operand for instruction # CHECK-ERROR-LABEL: vfmmacc.vv v8, v4, v20, v0.scale _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
