Skip to content

Commit a0b6cfd

Browse files
topperc4vtomat
andauthored
[RISCV] Add MC layer support for XSfmm*. (#133031)
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. --------- Co-authored-by: Brandon Wu <[email protected]>
1 parent ec9c8e9 commit a0b6cfd

22 files changed

+939
-6
lines changed

clang/test/Driver/print-supported-extensions-riscv.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@
170170
// CHECK-NEXT: xmipscmov 1.0 'XMIPSCMov' (MIPS conditional move instruction (mips.ccmov))
171171
// CHECK-NEXT: xmipslsp 1.0 'XMIPSLSP' (MIPS optimization for hardware load-store bonding)
172172
// CHECK-NEXT: xsfcease 1.0 'XSfcease' (SiFive sf.cease Instruction)
173+
// CHECK-NEXT: xsfmm128t 0.6 'XSfmm128t' (TE=128 configuration)
174+
// CHECK-NEXT: xsfmm16t 0.6 'XSfmm16t' (TE=16 configuration)
175+
// CHECK-NEXT: xsfmm32a16f 0.6 'XSfmm32a16f' (TEW=32-bit accumulation, operands - float: 16b, widen=2 (IEEE, BF))
176+
// CHECK-NEXT: xsfmm32a32f 0.6 'XSfmm32a32f' (TEW=32-bit accumulation, operands - float: 32b)
177+
// CHECK-NEXT: xsfmm32a8f 0.6 'XSfmm32a8f' (TEW=32-bit accumulation, operands - float: fp8)
178+
// CHECK-NEXT: xsfmm32a8i 0.6 'XSfmm32a8i' (TEW=32-bit accumulation, operands - int: 8b)
179+
// CHECK-NEXT: xsfmm32t 0.6 'XSfmm32t' (TE=32 configuration)
180+
// CHECK-NEXT: xsfmm64a64f 0.6 'XSfmm64a64f' (TEW=64-bit accumulation, operands - float: fp64)
181+
// CHECK-NEXT: xsfmm64t 0.6 'XSfmm64t' (TE=64 configuration)
182+
// CHECK-NEXT: xsfmmbase 0.6 'XSfmmbase' (All non arithmetic instructions for all TEWs and sf.vtzero)
173183
// CHECK-NEXT: xsfvcp 1.0 'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)
174184
// CHECK-NEXT: xsfvfnrclipxfqf 1.0 'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)
175185
// CHECK-NEXT: xsfvfwmaccqqq 1.0 'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// RUN: %clang --target=riscv32 \
2+
// RUN: -march=rv32i_zve32x_xsfmm128t -E -dM %s \
3+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
4+
// RUN: %clang --target=riscv64 \
5+
// RUN: -march=rv64i_zve32x_xsfmm128t -E -dM %s \
6+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM128T %s
7+
// CHECK-XSFMM128T: __riscv_xsfmm128t 6000{{$}}
8+
//
9+
// RUN: %clang --target=riscv32 \
10+
// RUN: -march=rv32i_zve32x_xsfmm16t -E -dM %s \
11+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
12+
// RUN: %clang --target=riscv64 \
13+
// RUN: -march=rv64i_zve32x_xsfmm16t -E -dM %s \
14+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM16T %s
15+
// CHECK-XSFMM16T: __riscv_xsfmm16t 6000{{$}}
16+
17+
// RUN: %clang --target=riscv32 \
18+
// RUN: -march=rv32i_zve32x_xsfmm32a8i -E -dM %s \
19+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
20+
// RUN: %clang --target=riscv64 \
21+
// RUN: -march=rv64i_zve32x_xsfmm32a8i -E -dM %s \
22+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a8I %s
23+
// CHECK-XSFMM32a8I: __riscv_xsfmm32a8i 6000{{$}}
24+
25+
// RUN: %clang --target=riscv32 \
26+
// RUN: -march=rv32i_zve32x_xsfmm32a8f -E -dM %s \
27+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
28+
// RUN: %clang --target=riscv64 \
29+
// RUN: -march=rv64i_zve32x_xsfmm32a8f -E -dM %s \
30+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32A8F %s
31+
// CHECK-XSFMM32A8F: __riscv_xsfmm32a8f 6000{{$}}
32+
33+
// RUN: %clang --target=riscv32 \
34+
// RUN: -march=rv32i_zve32x_xsfmm32a16f -E -dM %s \
35+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
36+
// RUN: %clang --target=riscv64 \
37+
// RUN: -march=rv64i_zve32x_xsfmm32a16f -E -dM %s \
38+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a16F %s
39+
// CHECK-XSFMM32a16F: __riscv_xsfmm32a16f 6000{{$}}
40+
41+
// RUN: %clang --target=riscv32 \
42+
// RUN: -march=rv32i_zve32x_xsfmm32a32f -E -dM %s \
43+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
44+
// RUN: %clang --target=riscv64 \
45+
// RUN: -march=rv64i_zve32x_xsfmm32a32f -E -dM %s \
46+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32a32F %s
47+
// CHECK-XSFMM32a32F: __riscv_xsfmm32a32f 6000{{$}}
48+
49+
// RUN: %clang --target=riscv32 \
50+
// RUN: -march=rv32i_zve32x_xsfmm32t -E -dM %s \
51+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
52+
// RUN: %clang --target=riscv64 \
53+
// RUN: -march=rv64i_zve32x_xsfmm32t -E -dM %s \
54+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM32T %s
55+
// CHECK-XSFMM32T: __riscv_xsfmm32t 6000{{$}}
56+
57+
// RUN: %clang --target=riscv32 \
58+
// RUN: -march=rv32i_zve32x_xsfmm64a64f -E -dM %s \
59+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
60+
// RUN: %clang --target=riscv64 \
61+
// RUN: -march=rv64i_zve32x_xsfmm64a64f -E -dM %s \
62+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64a64f %s
63+
// CHECK-XSFMM64a64f: __riscv_xsfmm64a64f 6000{{$}}
64+
65+
// RUN: %clang --target=riscv32 \
66+
// RUN: -march=rv32i_zve32x_xsfmm64t -E -dM %s \
67+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
68+
// RUN: %clang --target=riscv64 \
69+
// RUN: -march=rv64i_zve32x_xsfmm64t -E -dM %s \
70+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMM64T %s
71+
// CHECK-XSFMM64T: __riscv_xsfmm64t 6000{{$}}
72+
73+
// RUN: %clang --target=riscv32 \
74+
// RUN: -march=rv32i_zve32x_xsfmmbase -E -dM %s \
75+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
76+
// RUN: %clang --target=riscv64 \
77+
// RUN: -march=rv64i_zve32x_xsfmmbase -E -dM %s \
78+
// RUN: -o - | FileCheck --check-prefix=CHECK-XSFMMBASE %s
79+
// CHECK-XSFMMBASE: __riscv_xsfmmbase 6000{{$}}

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ The current vendor extensions supported are:
392392
``XVentanaCondOps``
393393
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.
394394

395+
``Xsfmm*``
396+
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.
397+
395398
``XSfvcp``
396399
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.
397400

llvm/docs/ReleaseNotes.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ Changes to the RISC-V Backend
197197
* Adds assembler support for the Andes `XAndesvdot` (Andes Vector Dot Product extension).
198198
* Adds assembler support for the standard `Q` (Quad-Precision Floating Point)
199199
extension.
200-
200+
* Adds experimental assembler support for the SiFive Xsfmm* Attached Matrix
201+
Extensions.
202+
201203
Changes to the WebAssembly Backend
202204
----------------------------------
203205

llvm/include/llvm/TargetParser/RISCVTargetParser.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
8989
unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
9090
bool MaskAgnostic);
9191

92+
unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
93+
9294
inline static VLMUL getVLMUL(unsigned VType) {
9395
unsigned VLMul = VType & 0x7;
9496
return static_cast<VLMUL>(VLMul);
@@ -118,10 +120,34 @@ inline static unsigned getSEW(unsigned VType) {
118120
return decodeVSEW(VSEW);
119121
}
120122

123+
inline static unsigned decodeTWiden(unsigned TWiden) {
124+
assert((TWiden == 1 || TWiden == 2 || TWiden == 3) &&
125+
"Unexpected TWiden value");
126+
return 1 << (TWiden - 1);
127+
}
128+
129+
inline static bool hasXSfmmWiden(unsigned VType) {
130+
unsigned TWiden = (VType >> 9) & 0x3;
131+
return TWiden != 0;
132+
}
133+
134+
inline static unsigned getXSfmmWiden(unsigned VType) {
135+
unsigned TWiden = (VType >> 9) & 0x3;
136+
assert(TWiden != 0 && "Invalid widen value");
137+
return 1 << (TWiden - 1);
138+
}
139+
140+
static inline bool isValidXSfmmVType(unsigned VTypeI) {
141+
return (VTypeI & ~0x738) == 0 && RISCVVType::hasXSfmmWiden(VTypeI) &&
142+
RISCVVType::getSEW(VTypeI) * RISCVVType::getXSfmmWiden(VTypeI) <= 64;
143+
}
144+
121145
inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
122146

123147
inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
124148

149+
inline static bool isAltFmt(unsigned VType) { return VType & 0x100; }
150+
125151
void printVType(unsigned VType, raw_ostream &OS);
126152

127153
unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul);

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
125125
bool &MaskAgnostic);
126126
bool generateVTypeError(SMLoc ErrorLoc);
127127

128+
bool generateXSfmmVTypeError(SMLoc ErrorLoc);
128129
// Helper to actually emit an instruction to the MCStreamer. Also, when
129130
// possible, compression of the instruction is performed.
130131
void emitToStreamer(MCStreamer &S, const MCInst &Inst);
@@ -221,6 +222,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
221222
}
222223

223224
ParseStatus parseRegReg(OperandVector &Operands);
225+
ParseStatus parseXSfmmVType(OperandVector &Operands);
224226
ParseStatus parseRetval(OperandVector &Operands);
225227
ParseStatus parseZcmpStackAdj(OperandVector &Operands,
226228
bool ExpectNegative = false);
@@ -634,6 +636,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
634636
return isUImm<11>();
635637
}
636638

639+
bool isXSfmmVType() const {
640+
return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
641+
}
642+
637643
/// Return true if the operand is a valid for the fence instruction e.g.
638644
/// ('iorw').
639645
bool isFenceArg() const { return Kind == KindTy::Fence; }
@@ -2342,6 +2348,65 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
23422348
"e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
23432349
}
23442350

2351+
ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
2352+
SMLoc S = getLoc();
2353+
2354+
unsigned Widen = 0;
2355+
unsigned SEW = 0;
2356+
bool AltFmt = false;
2357+
StringRef Identifier;
2358+
2359+
if (getTok().isNot(AsmToken::Identifier))
2360+
goto Fail;
2361+
2362+
Identifier = getTok().getIdentifier();
2363+
2364+
if (!Identifier.consume_front("e"))
2365+
goto Fail;
2366+
2367+
if (Identifier.getAsInteger(10, SEW)) {
2368+
if (Identifier != "16alt")
2369+
goto Fail;
2370+
2371+
AltFmt = true;
2372+
SEW = 16;
2373+
}
2374+
if (!RISCVVType::isValidSEW(SEW))
2375+
goto Fail;
2376+
2377+
Lex();
2378+
2379+
if (!parseOptionalToken(AsmToken::Comma))
2380+
goto Fail;
2381+
2382+
if (getTok().isNot(AsmToken::Identifier))
2383+
goto Fail;
2384+
2385+
Identifier = getTok().getIdentifier();
2386+
2387+
if (!Identifier.consume_front("w"))
2388+
goto Fail;
2389+
if (Identifier.getAsInteger(10, Widen))
2390+
goto Fail;
2391+
if (Widen != 1 && Widen != 2 && Widen != 4)
2392+
goto Fail;
2393+
2394+
Lex();
2395+
2396+
if (getLexer().is(AsmToken::EndOfStatement)) {
2397+
Operands.push_back(RISCVOperand::createVType(
2398+
RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2399+
return ParseStatus::Success;
2400+
}
2401+
2402+
Fail:
2403+
return generateXSfmmVTypeError(S);
2404+
}
2405+
2406+
bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2407+
return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2408+
}
2409+
23452410
ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
23462411
if (getLexer().isNot(AsmToken::Identifier))
23472412
return ParseStatus::NoMatch;

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,39 @@ static DecodeStatus DecodeVMV0RegisterClass(MCInst &Inst, uint32_t RegNo,
344344
return MCDisassembler::Success;
345345
}
346346

347+
static DecodeStatus DecodeTRRegisterClass(MCInst &Inst, uint32_t RegNo,
348+
uint64_t Address,
349+
const MCDisassembler *Decoder) {
350+
if (RegNo > 15)
351+
return MCDisassembler::Fail;
352+
353+
MCRegister Reg = RISCV::T0 + RegNo;
354+
Inst.addOperand(MCOperand::createReg(Reg));
355+
return MCDisassembler::Success;
356+
}
357+
358+
static DecodeStatus DecodeTRM2RegisterClass(MCInst &Inst, uint32_t RegNo,
359+
uint64_t Address,
360+
const MCDisassembler *Decoder) {
361+
if (RegNo > 15 || RegNo % 2)
362+
return MCDisassembler::Fail;
363+
364+
MCRegister Reg = RISCV::T0 + RegNo;
365+
Inst.addOperand(MCOperand::createReg(Reg));
366+
return MCDisassembler::Success;
367+
}
368+
369+
static DecodeStatus DecodeTRM4RegisterClass(MCInst &Inst, uint32_t RegNo,
370+
uint64_t Address,
371+
const MCDisassembler *Decoder) {
372+
if (RegNo > 15 || RegNo % 4)
373+
return MCDisassembler::Fail;
374+
375+
MCRegister Reg = RISCV::T0 + RegNo;
376+
Inst.addOperand(MCOperand::createReg(Reg));
377+
return MCDisassembler::Success;
378+
}
379+
347380
static DecodeStatus decodeVMaskReg(MCInst &Inst, uint32_t RegNo,
348381
uint64_t Address,
349382
const MCDisassembler *Decoder) {
@@ -722,9 +755,9 @@ static constexpr FeatureBitset XqciFeatureGroup = {
722755
};
723756

724757
static constexpr FeatureBitset XSfVectorGroup = {
725-
RISCV::FeatureVendorXSfvcp, RISCV::FeatureVendorXSfvqmaccdod,
726-
RISCV::FeatureVendorXSfvqmaccqoq, RISCV::FeatureVendorXSfvfwmaccqqq,
727-
RISCV::FeatureVendorXSfvfnrclipxfqf};
758+
RISCV::FeatureVendorXSfvcp, RISCV::FeatureVendorXSfvqmaccdod,
759+
RISCV::FeatureVendorXSfvqmaccqoq, RISCV::FeatureVendorXSfvfwmaccqqq,
760+
RISCV::FeatureVendorXSfvfnrclipxfqf, RISCV::FeatureVendorXSfmmbase};
728761
static constexpr FeatureBitset XSfSystemGroup = {
729762
RISCV::FeatureVendorXSiFivecdiscarddlone,
730763
RISCV::FeatureVendorXSiFivecflushdlone,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,20 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
227227
RISCVVType::printVType(Imm, O);
228228
}
229229

230+
void RISCVInstPrinter::printXSfmmVType(const MCInst *MI, unsigned OpNo,
231+
const MCSubtargetInfo &STI,
232+
raw_ostream &O) {
233+
unsigned Imm = MI->getOperand(OpNo).getImm();
234+
assert(RISCVVType::isValidXSfmmVType(Imm));
235+
unsigned SEW = RISCVVType::getSEW(Imm);
236+
O << "e" << SEW;
237+
bool AltFmt = RISCVVType::isAltFmt(Imm);
238+
if (AltFmt)
239+
O << "alt";
240+
unsigned Widen = RISCVVType::getXSfmmWiden(Imm);
241+
O << ", w" << Widen;
242+
}
243+
230244
// Print a Zcmp RList. If we are printing architectural register names rather
231245
// than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all
232246
// registers. Otherwise, we print "{ra, s0-s11}".

llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class RISCVInstPrinter : public MCInstPrinter {
4848
const MCSubtargetInfo &STI, raw_ostream &O);
4949
void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
5050
raw_ostream &O);
51+
void printXSfmmVType(const MCInst *MI, unsigned OpNo,
52+
const MCSubtargetInfo &STI, raw_ostream &O);
5153
void printVMaskReg(const MCInst *MI, unsigned OpNo,
5254
const MCSubtargetInfo &STI, raw_ostream &O);
5355
void printRegList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,

0 commit comments

Comments
 (0)