-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Add MC layer support for XSfmm*. #133031
base: main
Are you sure you want to change the base?
Conversation
This adds assembler/disassembler support for XSfmmbase 0.6 and related SiFive matrix multiplication extensions based on the spec here https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification Functionality-wise, this is the same as the Zvma extension proposal that SiFive shared with the Attached Matrix Extension Task Group. The extension names and instruction mnemonics have been changed to use vendor prefixes. Note the opcodes used here are in the standard opcode space in OP-V or OP-VE. Co-authored-by: Brandon Wu <brandon.wu@sifive.com>
@llvm/pr-subscribers-clang @llvm/pr-subscribers-mc Author: Craig Topper (topperc) ChangesThis adds assembler/disassembler support for XSfmmbase 0.6 and related SiFive matrix multiplication extensions based on the spec here https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification Functionality-wise, this is the same as the Zvma extension proposal that SiFive shared with the Attached Matrix Extension Task Group. The extension names and instruction mnemonics have been changed to use vendor prefixes. Note the opcodes used here are in the standard opcode space in OP-V or OP-VE. Patch is 59.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133031.diff 21 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 7e201b1149ec3..93f9e75b8413d 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -164,6 +164,18 @@
// CHECK-NEXT: xmipscmove 1.0 'XMIPSCMove' (MIPS conditional move instruction(s) (ccmov))
// CHECK-NEXT: xmipslsp 1.0 'XMIPSLSP' (MIPS optimization for hardware load-store bonding)
// CHECK-NEXT: xsfcease 1.0 'XSfcease' (SiFive sf.cease Instruction)
+// CHECK-NEXT: xsfmm128t 0.6 'XSfmm128t' (TE=128 configuration)
+// CHECK-NEXT: xsfmm16t 0.6 'XSfmm16t' (TE=16 configuration)
+// CHECK-NEXT: xsfmm32a 0.6 'XSfmm32a' (TEW=32-bit accumulation, operands - int: 8b; float: fp16, bf16, fp32)
+// CHECK-NEXT: xsfmm32a16f 0.6 'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF))
+// CHECK-NEXT: xsfmm32a32f 0.6 'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b)
+// CHECK-NEXT: xsfmm32a4i 0.6 'XSfmm32a4i' (TEW=32-bit accumulation, operands - int: 4b (packed))
+// CHECK-NEXT: xsfmm32a8f 0.6 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)
+// CHECK-NEXT: xsfmm32a8i 0.6 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)
+// CHECK-NEXT: xsfmm32t 0.6 'XSfmm32t' (TE=32 configuration)
+// CHECK-NEXT: xsfmm64a64f 0.6 'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)
+// CHECK-NEXT: xsfmm64t 0.6 'XSfmm64t' (TE=64 configuration)
+// CHECK-NEXT: xsfmmbase 0.6 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)
// CHECK-NEXT: xsfvcp 1.0 'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)
// CHECK-NEXT: xsfvfnrclipxfqf 1.0 'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)
// CHECK-NEXT: xsfvfwmaccqqq 1.0 'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))
diff --git a/clang/test/Preprocessor/riscv-target-features-sifive.c b/clang/test/Preprocessor/riscv-target-features-sifive.c
new file mode 100644
index 0000000000000..a57db60a1b326
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-target-features-sifive.c
@@ -0,0 +1,95 @@
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm128t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm128t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
+// CHECK-XSFMM128T: __riscv_xsfmm128t 6000{{$}}
+//
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm16t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm16t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
+// CHECK-XSFMM16T: __riscv_xsfmm16t 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A %s
+// CHECK-XSFMM32A: __riscv_xsfmm32a 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a4i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A4I %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a4i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A4I %s
+// CHECK-XSFMM32A4I: __riscv_xsfmm32a4i 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a8i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a8i -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
+// CHECK-XSFMM32a8I: __riscv_xsfmm32a8i 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a8f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a8f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
+// CHECK-XSFMM32A8F: __riscv_xsfmm32a8f 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a16f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a16f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
+// CHECK-XSFMM32a16F: __riscv_xsfmm32a16f 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32a32f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32a32f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
+// CHECK-XSFMM32a32F: __riscv_xsfmm32a32f 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm32t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm32t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
+// CHECK-XSFMM32T: __riscv_xsfmm32t 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm64a64f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm64a64f -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
+// CHECK-XSFMM64a64f: __riscv_xsfmm64a64f 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmm64t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmm64t -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
+// CHECK-XSFMM64T: __riscv_xsfmm64t 6000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN: -march=rv32i_zve32x_xsfmmbase -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// RUN: %clang --target=riscv64 \
+// RUN: -march=rv64i_zve32x_xsfmmbase -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
+// CHECK-XSFMMBASE: __riscv_xsfmmbase 6000{{$}}
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 8735b274a805f..1100b1a8fbe3c 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -389,6 +389,9 @@ The current vendor extensions supported are:
``XVentanaCondOps``
LLVM implements `version 1.0.0 of the VTx-family custom instructions specification <https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf>`__ by Ventana Micro Systems. All instructions are prefixed with `vt.` as described in the specification, and the riscv-toolchain-convention document linked above. These instructions are only available for riscv64 at this time.
+``Xsfmm*``
+ LLVM implements `version 0.6 of the Xsfmm Family of Attached Matrix Extensions Specification <https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification>`__ by SiFive. All instructions are prefixed with `sf.` as described in the specification.
+
``XSfvcp``
LLVM implements `version 1.1.0 of the SiFive Vector Coprocessor Interface (VCIX) Software Specification <https://sifive.cdn.prismic.io/sifive/Zn3m1R5LeNNTwnLS_vcix-spec-software-v1p1.pdf>`__ by SiFive. All instructions are prefixed with `sf.vc.` as described in the specification, and the riscv-toolchain-convention document linked above.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 445599fb9b770..b278e99d1adf3 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -152,6 +152,8 @@ Changes to the RISC-V Backend
handlers.
* When the experimental extension `Xqcili` is enabled, `qc.e.li` and `qc.li` may
now be used to materialize immediates.
+* Adds experimental assembler support for the SiFive Xsfmm* Attached Matrix
+ Extensions.
Changes to the WebAssembly Backend
----------------------------------
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index 6e231d32e7897..b4b6096f860bf 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -97,6 +97,8 @@ inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
bool MaskAgnostic);
+unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
+
inline static VLMUL getVLMUL(unsigned VType) {
unsigned VLMul = VType & 0x7;
return static_cast<VLMUL>(VLMul);
@@ -126,10 +128,36 @@ inline static unsigned getSEW(unsigned VType) {
return decodeVSEW(VSEW);
}
+inline static unsigned decodeTWiden(unsigned TWiden) {
+ assert((TWiden == 1 || TWiden == 2 || TWiden == 3) &&
+ "Unexpected TWiden value");
+ return 1 << (TWiden - 1);
+}
+
+inline static bool hasXSfmmWiden(unsigned VType) {
+ unsigned TWiden = (VType >> 9) & 0x3;
+ return TWiden != 0;
+}
+
+inline static unsigned getXSfmmWiden(unsigned VType) {
+ unsigned TWiden = (VType >> 9) & 0x3;
+ assert(TWiden != 0 && "Invalid widen value");
+ return 1 << (TWiden - 1);
+}
+
+inline static bool getXSfmmAltFmt(unsigned VType) { return (VType >> 8) & 1; }
+
+static inline bool isValidXSfmmVType(unsigned VTypeI) {
+ return (VTypeI & ~0x738) == 0 && RISCVVType::hasXSfmmWiden(VTypeI) &&
+ RISCVVType::getSEW(VTypeI) * RISCVVType::getXSfmmWiden(VTypeI) <= 64;
+}
+
inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
+inline static bool isAltFmt(unsigned VType) { return VType & 0x100; }
+
void printVType(unsigned VType, raw_ostream &OS);
unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul);
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 05997cf78c6b1..abe734b1dab20 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -77,6 +77,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
VTypeState_Done,
};
+ enum WWEEState {
+ WWEEState_Widen,
+ WWEEState_SEW,
+ WWEEState_Done,
+ };
+
SmallVector<FeatureBitset, 4> FeatureBitStack;
SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
@@ -125,6 +131,9 @@ class RISCVAsmParser : public MCTargetAsmParser {
bool &MaskAgnostic);
bool generateVTypeError(SMLoc ErrorLoc);
+ bool parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State, unsigned &WW,
+ unsigned &EE, bool &AltFmt);
+ bool generateXSfmmVTypeError(SMLoc ErrorLoc);
// Helper to actually emit an instruction to the MCStreamer. Also, when
// possible, compression of the instruction is performed.
void emitToStreamer(MCStreamer &S, const MCInst &Inst);
@@ -217,6 +226,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseFenceArg(OperandVector &Operands);
ParseStatus parseReglist(OperandVector &Operands);
ParseStatus parseRegReg(OperandVector &Operands);
+ ParseStatus parseXSfmmVType(OperandVector &Operands);
ParseStatus parseRetval(OperandVector &Operands);
ParseStatus parseZcmpStackAdj(OperandVector &Operands,
bool ExpectNegative = false);
@@ -622,6 +632,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return Kind == KindTy::VType;
}
+ bool isXSfmmVType() const {
+ return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
+ }
+
/// Return true if the operand is a valid for the fence instruction e.g.
/// ('iorw').
bool isFenceArg() const { return Kind == KindTy::Fence; }
@@ -2489,6 +2503,81 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
"e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
}
+bool RISCVAsmParser::parseXSfmmVTypeToken(const AsmToken &Tok, WWEEState &State,
+ unsigned &WW, unsigned &EE,
+ bool &AltFmt) {
+ if (getLexer().isNot(AsmToken::Identifier))
+ return true;
+
+ StringRef Identifier = getTok().getIdentifier();
+
+ switch (State) {
+ case WWEEState_SEW:
+ if (!Identifier.consume_front("e"))
+ break;
+ if (Identifier.getAsInteger(10, EE)) {
+ if (Identifier != "16alt")
+ break;
+
+ AltFmt = true;
+ EE = 16;
+ }
+ if (!RISCVVType::isValidSEW(EE))
+ break;
+ State = WWEEState_Widen;
+ return false;
+ case WWEEState_Widen:
+ if (!Identifier.consume_front("w"))
+ break;
+ if (Identifier.getAsInteger(10, WW))
+ break;
+ if (WW != 1 && WW != 2 && WW != 4)
+ break;
+ State = WWEEState_Done;
+ return false;
+ case WWEEState_Done:
+ // Extra token?
+ break;
+ }
+
+ return true;
+}
+
+ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
+ SMLoc S = getLoc();
+
+ unsigned Widen = 0;
+ unsigned SEW = 0;
+ bool AltFmt = false;
+
+ WWEEState State = WWEEState_SEW;
+
+ if (parseXSfmmVTypeToken(getTok(), State, Widen, SEW, AltFmt))
+ return generateXSfmmVTypeError(S);
+
+ getLexer().Lex();
+
+ if (!parseOptionalToken(AsmToken::Comma))
+ return generateXSfmmVTypeError(S);
+
+ if (parseXSfmmVTypeToken(getTok(), State, Widen, SEW, AltFmt))
+ return generateXSfmmVTypeError(S);
+
+ getLexer().Lex();
+
+ if (getLexer().is(AsmToken::EndOfStatement) && State == WWEEState_Done) {
+ Operands.push_back(RISCVOperand::createVType(
+ RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
+ return ParseStatus::Success;
+ }
+
+ return generateXSfmmVTypeError(S);
+}
+
+bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
+ return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
+}
+
ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
if (getLexer().isNot(AsmToken::Identifier))
return ParseStatus::NoMatch;
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 93cbf662bfa32..2c2ea82b5e892 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -323,6 +323,39 @@ static DecodeStatus DecodeVMV0RegisterClass(MCInst &Inst, uint32_t RegNo,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeTRRegisterClass(MCInst &Inst, uint32_t RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ if (RegNo > 15)
+ return MCDisassembler::Fail;
+
+ MCRegister Reg = RISCV::T0 + RegNo;
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM2RegisterClass(MCInst &Inst, uint32_t RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ if (RegNo > 15 || RegNo % 2)
+ return MCDisassembler::Fail;
+
+ MCRegister Reg = RISCV::T0 + RegNo;
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeTRM4RegisterClass(MCInst &Inst, uint32_t RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ if (RegNo > 15 || RegNo % 4)
+ return MCDisassembler::Fail;
+
+ MCRegister Reg = RISCV::T0 + RegNo;
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeVMaskReg(MCInst &Inst, uint32_t RegNo,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -707,6 +740,7 @@ static constexpr DecoderListEntry DecoderList32[]{
"XVentanaCondOps"},
{DecoderTableXTHead32, XTHeadGroup, "T-Head extensions"},
{DecoderTableXSfvector32, XSfVectorGroup, "SiFive vector extensions"},
+ {DecoderTableXSfmm32, {RISCV::FeatureVendorXSfmmbase}, "SiFive XSfmm"},
{DecoderTableXSfsystem32, XSfSystemGroup, "SiFive system extensions"},
{DecoderTableXSfcease32, {RISCV::FeatureVendorXSfcease}, "SiFive sf.cease"},
{DecoderTableXmipslsp32, {RISCV::FeatureVendorXMIPSLSP}, "MIPS mips.lsp"},
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index a4a40862a67c6..f7aebac205ce7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -219,6 +219,20 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
RISCVVType::printVType(Imm, O);
}
+void RISCVInstPrinter::printXSfmmVType(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNo).getImm();
+ assert(RISCVVType::isValidXSfmmVType(Imm));
+ unsigned SEW = RISCVVType::getSEW(Imm);
+ O << "e" << SEW;
+ bool AltFmt = RISCVVType::getXSfmmAltFmt(Imm);
+ if (AltFmt)
+ O << "alt";
+ unsigned Widen = RISCVVType::getXSfmmWiden(Imm);
+ O << ", w" << Widen;
+}
+
// Print a Zcmp RList. If we are printing architectural register names rather
// than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all
// registers. Otherwise, we print "{ra, s0-s11}".
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
index 6d4928ee64ec9..e4846c427beb7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -48,6 +48,8 @@ class RISCVInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
+ void printXSfmmVType(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printVMaskReg(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 5ed3ed917aa4c..2b42524e4fa2c 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1176,6 +1176,86 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
AssemblerPredicate<(all_of FeatureVendorXSfvcp),
"'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;
+def FeatureVendorXSfmmbase
+ : RISCVExtension<0, 6,
+ "All non arithmetic instructions for all TEWs and sf.vtzero",
+ [FeatureStdExtZve32x]>;
+def HasVendorXSfmmbase : Predicate<"Subtarget->hasVendorXSfmmbase()">,
+ AssemblerPredicate<(all_of FeatureVendorXSfmmbase),
+ "'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)">;
+
+def FeatureVendorXSfmm32a8f
+ : RISCVExtension<0, 6,
+ "TEW=32-bit accumulation, operands - float: fp8",
+ [FeatureVendorXSfmmbase, FeatureStdExtZve32f]>;
+def HasVendorXSfmm32a8f : Predicate<"Subtarget->hasVendorXSfmm32a8f()">,
+ AssemblerPredicate<(all_of FeatureVendorXSf...
[truncated]
|
Thanks for the tests on the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have followed the progress of IME/AME for a long time, there are several candidates in parallel. I think the support of these extensions should be marked as early access, and we can review these patches but won't merge them until they are ratified just like Zvzip/Zvabd/Zibimm/...
DwarfRegNum<[!add(Index, 3072)]>; | ||
|
||
let RegInfos = XLenRI in { | ||
def TR : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a PoC to use Target Extension Type to support matrix, does SiFive try this machanism in the CodeGen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have done some experiment with that, but our current thought is to use constant "tile id" for intrinsics instead of allocating tiles in compiler. This what AArch64 SME does.
This ISA doesn't support load, store, or copy of whole tiles. These require loops to emulate using vector registers.
I think using Target Extension Type still needs an underlying type to calculate size. The tiles here are scalable in two dimensions which TypeSize
can't represent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tiles here are scalable in two dimensions which TypeSize can't represent.
Yeah, we encountered the same problem and this is why XuanTie's AME is designed as that two dimensions are related IIRC.
I think this patch is supported to be the vendor instruction set of AME is another issue that we don’t have ratified AME but just SiFive AME proposal, XuanTie AME proposal. |
SiFive's AME proposal locates in OP-V/OP-VE category, I think it is not designed as vendor extension. IIUC, this patch is just for early evaluation. |
Yes, this is a good point. |
The RISC-V specification does not take a hard stance on non-conforming extensions. It should not be consider "abusing". Whether a non-concforming extensions is allowed is up to indvidual platform requirements. We have discussed in the past about taking patches for the T-Head 0.7 vector extension. I think we were willing to take it if there was a promise of continued maintenance. |
SiFive is committed to maintaining this implementation and we would very much like to see it in tree to enable easier sharing and avoid continual rebasing. Expect to see patches for intrinsics in the near future. |
We have discussed whether to accept non-conforming vendor extensions in the past. Our consensus was clearly documented in RISCVUsage.rst in the statement " In particular, we expect to eventually accept both custom extensions and non-conforming extensions." This is a non-conforming vendor extension, and that needs to be clearly described, but it is not blocking for whether we accept the change. |
This adds assembler/disassembler support for XSfmmbase 0.6 and related SiFive matrix multiplication extensions based on the spec here https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification
Functionality-wise, this is the same as the Zvma extension proposal that SiFive shared with the Attached Matrix Extension Task Group. The extension names and instruction mnemonics have been changed to use vendor prefixes.
Note this is a non-conforming extension as the opcodes used here are in the standard opcode space in OP-V or OP-VE.