[llvm] [llvm][mc][riscv] MC support of T-Head vector extension (xtheadvector) (PR #84447)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 8 00:47:36 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: None (kata-ark)
<details>
<summary>Changes</summary>
This PR adds the following support of [the T-Head vector extension](https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadvector.adoc):
1. added extension info, dependencies, and versions to `RISCVISAInfo.cpp`.
2. added MC support of the assembler instructions of the t-head vector.
3. added corresponding MC tests according to [the GNU AS test file](https://github.com/riscvarchive/riscv-binutils-gdb/blob/rvv-0.7.1/gas/testsuite/gas/riscv/vector-insns.d).
The t-head vector is very similar to RVV 1.0, according to [the t-head vector spec](https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadvector.adoc), but all assembler instructions are prefixed with `th.`. This PR implements the MC support by creating a new decoder namespace. We are looking for an elegant method to reuse existing instructions from `RISCVInstrInfoV.td` automatically, without adding any TableGen symbol for the "same instructions" (only names are prefixed with `th.`) between RVV 1.0 and T-Head Vector.
Last week we opened a [discussion on discourse](https://discourse.llvm.org/t/questions-about-the-t-head-vector-extension-xtheadvector-in-llvm-upstream/77298/2), and this PR may answer some questions there. Any comments and suggestions are welcomed and appreciated!!
---
Patch is 614.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/84447.diff
48 Files Affected:
- (modified) llvm/include/llvm/TargetParser/RISCVTargetParser.h (+14)
- (modified) llvm/lib/Support/RISCVISAInfo.cpp (+28-5)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+208-42)
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+2)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp (+15)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h (+2)
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+19)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+1)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+1)
- (added) llvm/lib/Target/RISCV/RISCVInstrInfoXTHeadV.td (+967)
- (modified) llvm/lib/TargetParser/RISCVTargetParser.cpp (+28)
- (modified) llvm/test/MC/RISCV/attribute-arch.s (+12)
- (added) llvm/test/MC/RISCV/xtheadvector/add.s (+309)
- (added) llvm/test/MC/RISCV/xtheadvector/and.s (+45)
- (added) llvm/test/MC/RISCV/xtheadvector/clip.s (+81)
- (added) llvm/test/MC/RISCV/xtheadvector/compare.s (+256)
- (added) llvm/test/MC/RISCV/xtheadvector/convert.s (+186)
- (added) llvm/test/MC/RISCV/xtheadvector/div.s (+105)
- (added) llvm/test/MC/RISCV/xtheadvector/fadd.s (+84)
- (added) llvm/test/MC/RISCV/xtheadvector/fcompare.s (+162)
- (added) llvm/test/MC/RISCV/xtheadvector/fdiv.s (+48)
- (added) llvm/test/MC/RISCV/xtheadvector/fmacc.s (+300)
- (added) llvm/test/MC/RISCV/xtheadvector/fminmax.s (+60)
- (added) llvm/test/MC/RISCV/xtheadvector/fmul.s (+60)
- (added) llvm/test/MC/RISCV/xtheadvector/fmv.s (+30)
- (added) llvm/test/MC/RISCV/xtheadvector/fothers.s (+40)
- (added) llvm/test/MC/RISCV/xtheadvector/freduction.s (+90)
- (added) llvm/test/MC/RISCV/xtheadvector/fsub.s (+96)
- (added) llvm/test/MC/RISCV/xtheadvector/load.s (+345)
- (added) llvm/test/MC/RISCV/xtheadvector/macc.s (+273)
- (added) llvm/test/MC/RISCV/xtheadvector/mask.s (+141)
- (added) llvm/test/MC/RISCV/xtheadvector/minmax.s (+105)
- (added) llvm/test/MC/RISCV/xtheadvector/mul.s (+201)
- (added) llvm/test/MC/RISCV/xtheadvector/mv.s (+39)
- (added) llvm/test/MC/RISCV/xtheadvector/or.s (+45)
- (added) llvm/test/MC/RISCV/xtheadvector/others.s (+141)
- (added) llvm/test/MC/RISCV/xtheadvector/reduction.s (+135)
- (added) llvm/test/MC/RISCV/xtheadvector/shift.s (+267)
- (added) llvm/test/MC/RISCV/xtheadvector/sign-injection.s (+84)
- (added) llvm/test/MC/RISCV/xtheadvector/store.s (+201)
- (added) llvm/test/MC/RISCV/xtheadvector/sub.s (+273)
- (added) llvm/test/MC/RISCV/xtheadvector/vector-insns.s (+6856)
- (added) llvm/test/MC/RISCV/xtheadvector/vsetvl-invaild.s (+15)
- (added) llvm/test/MC/RISCV/xtheadvector/vsetvl.s (+118)
- (added) llvm/test/MC/RISCV/xtheadvector/xor.s (+45)
- (added) llvm/test/MC/RISCV/xtheadvector/zvlsseg.s (+3370)
- (modified) llvm/unittests/Support/RISCVISAInfoTest.cpp (+8)
``````````diff
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index cdd19189f8dc7d..36ec58ea3469c1 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -69,9 +69,16 @@ inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1);
}
+// Is this a EDIV value that can be encoded into the VTYPE format.
+inline static bool isValidEDIV(unsigned EDIV) {
+ return isPowerOf2_32(EDIV) && EDIV <= 8;
+}
+
unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
bool MaskAgnostic);
+unsigned encodeXTHeadVTYPE(unsigned SEW, unsigned LMUL, unsigned EDIV);
+
inline static RISCVII::VLMUL getVLMUL(unsigned VType) {
unsigned VLMUL = VType & 0x7;
return static_cast<RISCVII::VLMUL>(VLMUL);
@@ -101,12 +108,19 @@ inline static unsigned getSEW(unsigned VType) {
return decodeVSEW(VSEW);
}
+inline static unsigned encodeEDIV(unsigned EDIV) {
+ assert(isValidEDIV(EDIV) && "Unexpected EDIV value");
+ return Log2_32(EDIV);
+}
+
inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
void printVType(unsigned VType, raw_ostream &OS);
+void printXTHeadVType(unsigned VType, raw_ostream &OS);
+
unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul);
std::optional<RISCVII::VLMUL>
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 6eec03fd6f7082..f8f8b152c20eca 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -106,6 +106,8 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
{"xtheadmempair", {1, 0}},
{"xtheadsync", {1, 0}},
{"xtheadvdot", {1, 0}},
+ {"xtheadvector", {1, 0}},
+ {"xtheadzvamo", {1, 0}},
{"xventanacondops", {1, 0}},
{"za128rs", {1, 0}},
@@ -368,6 +370,18 @@ static StringRef getExtensionType(StringRef Ext) {
return StringRef();
}
+static const RISCVSupportedExtension *
+findExtensionIn(llvm::ArrayRef<RISCVSupportedExtension> ExtensionInfos,
+ StringRef Ext, unsigned MajorVersion, unsigned MinorVersion) {
+ auto Range = std::equal_range(ExtensionInfos.begin(), ExtensionInfos.end(),
+ Ext, LessExtName());
+ for (auto I = Range.first, E = Range.second; I != E; ++I)
+ if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion) {
+ return I;
+ }
+ return ExtensionInfos.end();
+}
+
static std::optional<RISCVISAInfo::ExtensionVersion>
isExperimentalExtension(StringRef Ext) {
auto I =
@@ -406,11 +420,8 @@ bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
unsigned MinorVersion) {
for (auto ExtInfo : {ArrayRef(SupportedExtensions),
ArrayRef(SupportedExperimentalExtensions)}) {
- auto Range =
- std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
- for (auto I = Range.first, E = Range.second; I != E; ++I)
- if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
- return true;
+ return findExtensionIn(ExtInfo, Ext, MajorVersion, MinorVersion) !=
+ ExtInfo.end();
}
return false;
@@ -1038,6 +1049,16 @@ Error RISCVISAInfo::checkDependency() {
return createStringError(errc::invalid_argument,
"'zcf' is only supported for 'rv32'");
+ if (Exts.count("xtheadzvamo") && !Exts.count("a"))
+ return createStringError(
+ errc::invalid_argument,
+ "'xtheadzvamo' requires 'a' extension to also be specified");
+
+ if (Exts.count("xtheadvector") && HasVector)
+ return createStringError(
+ errc::invalid_argument,
+ "'xtheadvector' extension is incompatible with 'v' or 'zve*' extension");
+
return Error::success();
}
@@ -1045,6 +1066,7 @@ static const char *ImpliedExtsD[] = {"f"};
static const char *ImpliedExtsF[] = {"zicsr"};
static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"};
static const char *ImpliedExtsXTHeadVdot[] = {"v"};
+static const char *ImpliedExtsXTHeadZvamo[] = {"a"};
static const char *ImpliedExtsXSfvcp[] = {"zve32x"};
static const char *ImpliedExtsXSfvfnrclipxfqf[] = {"zve32f"};
static const char *ImpliedExtsXSfvfwmaccqqq[] = {"zvfbfmin"};
@@ -1125,6 +1147,7 @@ static constexpr ImpliedExtsEntry ImpliedExts[] = {
{{"xsfvqmaccdod"}, {ImpliedExtsXSfvqmaccdod}},
{{"xsfvqmaccqoq"}, {ImpliedExtsXSfvqmaccqoq}},
{{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
+ {{"xtheadzvamo"}, {ImpliedExtsXTHeadZvamo}},
{{"zabha"}, {ImpliedExtsZabha}},
{{"zacas"}, {ImpliedExtsZacas}},
{{"zcb"}, {ImpliedExtsZcb}},
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index d83979a873f2a3..32d08cfeafe2cd 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -163,6 +163,13 @@ class RISCVAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo vmsge{u}.vx instruction.
void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo vmsge{u}.vi instruction.
+ void emitVMSGE_VI(MCInst &Inst, unsigned Opcode, unsigned OpcodeImmIs0,
+ SMLoc IDLoc, MCStreamer &Out, bool IsSigned);
+
+ // Helper to emit pseudo vmsge{u}.vx instruction for XTHeadV extension.
+ void emitVMSGE_TH(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
+
// Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
// Enforcing this using a restricted register class for the second input
// operand of PseudoAddTPRel results in a poor diagnostic due to the fact
@@ -201,6 +208,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
ParseStatus parseJALOffset(OperandVector &Operands);
ParseStatus parseVTypeI(OperandVector &Operands);
+ ParseStatus parseXTHeadVTypeI(OperandVector &Operands);
ParseStatus parseMaskReg(OperandVector &Operands);
ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
@@ -329,6 +337,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
FPImmediate,
SystemRegister,
VType,
+ XTHeadVType,
FRM,
Fence,
Rlist,
@@ -422,6 +431,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
SysReg = o.SysReg;
break;
case KindTy::VType:
+ case KindTy::XTHeadVType:
VType = o.VType;
break;
case KindTy::FRM:
@@ -588,6 +598,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return isVTypeImm(11);
return Kind == KindTy::VType;
}
+ bool isXTHeadVTypeI() const {
+ if (Kind == KindTy::Immediate)
+ return isVTypeImm(11);
+ return Kind == KindTy::XTHeadVType;
+ }
/// Return true if the operand is a valid for the fence instruction e.g.
/// ('iorw').
@@ -1002,7 +1017,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}
unsigned getVType() const {
- assert(Kind == KindTy::VType && "Invalid type access!");
+ assert((Kind == KindTy::VType || Kind == KindTy::XTHeadVType) &&
+ "Invalid type access!");
return VType.Val;
}
@@ -1044,6 +1060,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
RISCVVType::printVType(getVType(), OS);
OS << '>';
break;
+ case KindTy::XTHeadVType:
+ OS << "<vtype: ";
+ RISCVVType::printXTHeadVType(getVType(), OS);
+ OS << '>';
+ break;
case KindTy::FRM:
OS << "<frm: ";
roundingModeToString(getFRM());
@@ -1168,6 +1189,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return Op;
}
+ static std::unique_ptr<RISCVOperand> createXTHeadVType(unsigned VTypeI, SMLoc S) {
+ auto Op = std::make_unique<RISCVOperand>(KindTy::XTHeadVType);
+ Op->VType.Val = VTypeI;
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
assert(Expr && "Expr shouldn't be null!");
int64_t Imm = 0;
@@ -1592,6 +1621,13 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return generateVTypeError(ErrorLoc);
}
+ case Match_InvalidXTHeadVTypeI: {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(
+ ErrorLoc,
+ "operand must be "
+ "e[8|16|32|64|128|256|512|1024],m[1|2|4|8],d[1|2|4|8] for XTHeadVector");
+ }
case Match_InvalidVMaskRegister: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be v0.t");
@@ -2225,6 +2261,57 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
"e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
}
+ParseStatus RISCVAsmParser::parseXTHeadVTypeI(OperandVector &Operands) {
+ SMLoc S = getLoc();
+ if (getLexer().isNot(AsmToken::Identifier))
+ return ParseStatus::NoMatch;
+
+ SmallVector<AsmToken, 7> VTypeIElements;
+ auto MatchFail = [&]() {
+ while (!VTypeIElements.empty())
+ getLexer().UnLex(VTypeIElements.pop_back_val());
+ return ParseStatus::NoMatch;
+ };
+
+ // Put all the tokens for vtypei operand into VTypeIElements vector.
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+ VTypeIElements.push_back(getLexer().getTok());
+ getLexer().Lex();
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+ if (getLexer().isNot(AsmToken::Comma))
+ return MatchFail();
+ AsmToken Comma = getLexer().getTok();
+ VTypeIElements.push_back(Comma);
+ getLexer().Lex();
+ }
+
+ if (VTypeIElements.size() == 5) {
+ // The VTypeIElements layout is:
+ // SEW comma LMUL comma EDIV
+ // 0 1 2 3 4
+ StringRef Prefix[] = {"e", "m", "d"};
+ unsigned VTypeEle[3];
+ for (size_t i = 0; i < 3; ++i) {
+ StringRef Name = VTypeIElements[2 * i].getIdentifier();
+ if (!Name.consume_front(Prefix[i]) || Name.getAsInteger(10, VTypeEle[i]))
+ return MatchFail();
+ }
+
+ if (!RISCVVType::isValidSEW(VTypeEle[0]) ||
+ !RISCVVType::isValidLMUL(VTypeEle[1], false) ||
+ !RISCVVType::isValidEDIV(VTypeEle[2]))
+ return MatchFail();
+
+ unsigned VTypeI =
+ RISCVVType::encodeXTHeadVTYPE(VTypeEle[0], VTypeEle[1], VTypeEle[2]);
+ Operands.push_back(RISCVOperand::createXTHeadVType(VTypeI, S));
+ return ParseStatus::Success;
+ }
+
+ return MatchFail();
+}
+
ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
if (getLexer().isNot(AsmToken::Identifier))
return ParseStatus::NoMatch;
@@ -3339,6 +3426,92 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
}
}
+
+void RISCVAsmParser::emitVMSGE_VI(MCInst &Inst, unsigned Opcode,
+ unsigned OpcodeImmIs0, SMLoc IDLoc,
+ MCStreamer &Out, bool IsSigned) {
+ int64_t Imm = Inst.getOperand(2).getImm();
+ if (IsSigned) {
+ // These instructions are signed and so is immediate so we can subtract one.
+ emitToStreamer(Out, MCInstBuilder(Opcode)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addImm(Imm - 1)
+ .addOperand(Inst.getOperand(3)));
+ } else {
+ // Unsigned comparisons are tricky because the immediate is signed. If the
+ // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
+ // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
+ // vmsne v0, v1, v1 which is always false.
+ if (Imm == 0) {
+ emitToStreamer(Out, MCInstBuilder(OpcodeImmIs0)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(3)));
+ } else {
+ // Other immediate values can subtract one like signed.
+ emitToStreamer(Out, MCInstBuilder(Opcode)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addImm(Imm - 1)
+ .addOperand(Inst.getOperand(3)));
+ }
+ }
+}
+
+void RISCVAsmParser::emitVMSGE_TH(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // https://github.com/riscv/riscv-v-spec/releases/tag/0.7.1
+ if (Inst.getNumOperands() == 3) {
+ // unmasked va >= x
+ //
+ // pseudoinstruction: vmsge{u}.vx vd, va, x
+ // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
+ emitToStreamer(Out, MCInstBuilder(Opcode)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(2))
+ .addReg(RISCV::NoRegister));
+ emitToStreamer(Out, MCInstBuilder(RISCV::TH_VMNAND_MM)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(0)));
+ } else if (Inst.getNumOperands() == 4) {
+ // masked va >= x, vd != v0
+ //
+ // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
+ // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
+ assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
+ "The destination register should not be V0.");
+ emitToStreamer(Out, MCInstBuilder(Opcode)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(2))
+ .addOperand(Inst.getOperand(3)));
+ emitToStreamer(Out, MCInstBuilder(RISCV::TH_VMXOR_MM)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(0))
+ .addReg(RISCV::V0));
+ } else if (Inst.getNumOperands() == 5) {
+ // masked va >= x, any vd
+ //
+ // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
+ // expansion: vmslt{u}.vx vt, va, x; vmandnot.mm vd, vd, vt
+ assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
+ "The temporary vector register should not be V0.");
+ emitToStreamer(Out, MCInstBuilder(Opcode)
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(2))
+ .addOperand(Inst.getOperand(3))
+ .addReg(RISCV::NoRegister));
+ emitToStreamer(Out, MCInstBuilder(RISCV::TH_VMANDN_MM)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1)));
+ }
+}
+
bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
OperandVector &Operands) {
assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
@@ -3385,7 +3558,9 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst,
unsigned Opcode = Inst.getOpcode();
if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
- Opcode == RISCV::PseudoVMSGE_VX_M_T) {
+ Opcode == RISCV::PseudoVMSGE_VX_M_T ||
+ Opcode == RISCV::PseudoTH_VMSGEU_VX_M_T ||
+ Opcode == RISCV::PseudoTH_VMSGE_VX_M_T) {
unsigned DestReg = Inst.getOperand(0).getReg();
unsigned TempReg = Inst.getOperand(1).getReg();
if (DestReg == TempReg) {
@@ -3627,49 +3802,40 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
return false;
case RISCV::PseudoVMSGE_VI:
- case RISCV::PseudoVMSLT_VI: {
- // These instructions are signed and so is immediate so we can subtract one
- // and change the opcode.
- int64_t Imm = Inst.getOperand(2).getImm();
- unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
- : RISCV::VMSLE_VI;
- emitToStreamer(Out, MCInstBuilder(Opc)
- .addOperand(Inst.getOperand(0))
- .addOperand(Inst.getOperand(1))
- .addImm(Imm - 1)
- .addOperand(Inst.getOperand(3)));
+ emitVMSGE_VI(Inst, RISCV::VMSGT_VI, RISCV::VMSGT_VI, IDLoc, Out, true);
+ return false;
+ case RISCV::PseudoVMSLT_VI:
+ emitVMSGE_VI(Inst, RISCV::VMSLE_VI, RISCV::VMSLE_VI, IDLoc, Out, true);
return false;
- }
case RISCV::PseudoVMSGEU_VI:
- case RISCV::PseudoVMSLTU_VI: {
- int64_t Imm = Inst.getOperand(2).getImm();
- // Unsigned comparisons are tricky because the immediate is signed. If the
- // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
- // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
- // vmsne v0, v1, v1 which is always false.
- if (Imm == 0) {
- unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
- ? RISCV::VMSEQ_VV
- : RISCV::VMSNE_VV;
- emitToStreamer(Out, MCInstBuilder(Opc)
- .addOperand(Inst.getOperand(0))
- .addOperand(Inst.getOperand(1))
- .addOperand(Inst.getOperand(1))
- .addOperand(Inst.getOperand(3)));
- } else {
- // Other immediate values can subtract one like signed.
- unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
- ? RISCV::VMSGTU_VI
- : RISCV::VMSLEU_VI;
- emitToStreamer(Out, MCInstBuilder(Opc)
- .addOperand(Inst.getOperand(0))
- .addOperand(Inst.getOperand(1))
- .addImm(Imm - 1)
- .addOperand(Inst.getOperand(3)));
- }
-
+ emitVMSGE_VI(Inst, RISCV::VMSGTU_VI, RISCV::VMSEQ_VV, IDLoc, Out, false);
+ return false;
+ case RISCV::PseudoVMSLTU_VI:
+ emitVMSGE_VI(Inst, RISCV::VMSLEU_VI, RISCV::VMSNE_VV, IDLoc, Out, false);
+ return false;
+ // for XTHeadVector Extension
+ case RISCV::PseudoTH_VMSGEU_VX:
+ case RISCV::PseudoTH_VMSGEU_VX_M:
+ case RISCV::PseudoTH_VMSGEU_VX_M_T:
+ emitVMSGE_TH(Inst, RISCV::TH_VMSLTU_VX, IDLoc, Out);
+ return false;
+ case RISCV::PseudoTH_VMSGE_VX:
+ case RISCV::PseudoTH_VMSGE_VX_M:
+ case RISCV::PseudoTH_VMSGE_VX_M_T:
+ emitVMSGE_TH(Inst, RISCV::TH_VMSLT_VX, IDLoc, Out);
+ return false;
+ case RISCV::PseudoTH_VMSGE_VI:
+ emitVMSGE_VI(Inst, RISCV::TH_VMSGT_VI, RISCV::TH_VMSGT_VI, IDLoc, Out, true);
+ return false;
+ case RISCV::PseudoTH_VMSLT_VI:
+ emitVMSGE_VI(Inst, RISCV::TH_VMSLE_VI, RISCV::TH_VMSLE_VI, IDLoc, Out, true);
+ return false;
+ case RISCV::PseudoTH_VMSGEU_VI:
+ emitVMSGE_VI(Inst, RISCV::TH_VMSGTU_VI, RISCV::TH_VMSEQ_VV, IDLoc, Out, false);
+ return false;
+ case RISCV::PseudoTH_VMSLTU_VI:
+ emitVMSGE_VI(Inst, RISCV::TH_VMSLEU_VI, RISCV::TH_VMSNE_VV, IDLoc, Out, false);
return false;
- }
}
emitToStreamer(Out, Inst);
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index f1ca1212ec378e..656bd5aac47ea5 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -581,6 +581,8 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
"XTHeadSync custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadVdot, DecoderTableXTHeadVdot32,
"XTHeadVdot custom opcode table");
+ TRY_T...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/84447
More information about the llvm-commits
mailing list