[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