[clang] c39dd7c - [RISCV][MC] Add support for RV64E

Alex Bradbury via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 23 05:32:56 PDT 2023


Author: Job Noorman
Date: 2023-03-23T12:32:25Z
New Revision: c39dd7c1db97fa367cb6282067b74cd8e55ef09a

URL: https://github.com/llvm/llvm-project/commit/c39dd7c1db97fa367cb6282067b74cd8e55ef09a
DIFF: https://github.com/llvm/llvm-project/commit/c39dd7c1db97fa367cb6282067b74cd8e55ef09a.diff

LOG: [RISCV][MC] Add support for RV64E

Implement MC support for the recently ratified RV64E base instruction
set.

Differential Revision: https://reviews.llvm.org/D143570

Added: 
    llvm/test/CodeGen/RISCV/rve.ll
    llvm/test/MC/RISCV/rv64e-valid.s

Modified: 
    clang/test/Driver/riscv-arch.c
    clang/test/Driver/riscv-features.c
    llvm/docs/RISCVUsage.rst
    llvm/docs/ReleaseNotes.rst
    llvm/lib/Support/RISCVISAInfo.cpp
    llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
    llvm/lib/Target/RISCV/RISCVFeatures.td
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/MC/RISCV/attribute-arch.s
    llvm/test/MC/RISCV/elf-flags.s
    llvm/test/MC/RISCV/invalid-attribute.s
    llvm/test/MC/RISCV/rv32e-invalid.s
    llvm/test/MC/RISCV/rv32e-valid.s
    llvm/test/MC/RISCV/target-abi-invalid.s
    llvm/test/MC/RISCV/target-abi-valid.s
    llvm/unittests/Support/RISCVISAInfoTest.cpp

Removed: 
    llvm/test/CodeGen/RISCV/mattr-invalid-combination.ll
    llvm/test/CodeGen/RISCV/rv32e.ll
    llvm/test/MC/RISCV/mattr-invalid-combination.s


################################################################################
diff  --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c
index 610f79d64ada2..cbc1464cbcd6f 100644
--- a/clang/test/Driver/riscv-arch.c
+++ b/clang/test/Driver/riscv-arch.c
@@ -198,11 +198,6 @@
 
 // Testing specific messages and unsupported extensions.
 
-// RUN: %clang --target=riscv64-unknown-elf -march=rv64e -### %s \
-// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64E %s
-// RV64E: error: invalid arch name 'rv64e',
-// RV64E: standard user-level extension 'e' requires 'rv32'
-
 // RUN: %clang --target=riscv32-unknown-elf -march=rv32imC -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LOWER %s
 // RV32-LOWER: error: invalid arch name 'rv32imC',
@@ -223,11 +218,6 @@
 // RV32-ORDER: error: invalid arch name 'rv32imcq',
 // RV32-ORDER: standard user-level extension not given in canonical order 'q'
 
-// RUN: %clang --target=riscv32-unknown-elf -march=rv64e -### %s \
-// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64-EER %s
-// RV64-EER: error: invalid arch name 'rv64e',
-// RV64-EER: standard user-level extension 'e' requires 'rv32'
-
 // RUN: %clang --target=riscv32-unknown-elf -march=rv32izve32f -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZVE32F-ER %s
 // RV32-ZVE32F-ER: error: invalid arch name 'rv32izve32f',

diff  --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c
index 98445b1920301..b189fdeacec8c 100644
--- a/clang/test/Driver/riscv-features.c
+++ b/clang/test/Driver/riscv-features.c
@@ -33,10 +33,6 @@
 // DEFAULT-LINUX-SAME: "-target-feature" "+d"
 // DEFAULT-LINUX-SAME: "-target-feature" "+c"
 
-// RUN: not %clang -cc1 -triple riscv64-unknown-elf -target-feature +e 2>&1 | FileCheck %s -check-prefix=RV64-WITH-E
-
-// RV64-WITH-E: error: invalid feature combination: standard user-level extension 'e' requires 'rv32'
-
 // RUN: not %clang -c --target=riscv64-linux-gnu -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefix=ERR-SPLIT-DWARF
 // RUN: not %clang -c --target=riscv64 -gsplit-dwarf=single %s 2>&1 | FileCheck %s --check-prefix=ERR-SPLIT-DWARF
 // RUN: %clang -### -c --target=riscv64 -mno-relax -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefix=SPLIT-DWARF

diff  --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 429b59a8d9404..ffd1028cedd80 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -15,9 +15,9 @@ supported variations of the RISC-V specification.  It lives in the
 Base ISAs
 =========
 
-The specification defines four base instruction sets: RV32I, RV32E, RV64I,
-and RV128I. Currently, LLVM fully supports RV32I, and RV64I.  RV32E is
-supported by the assembly-based tools only.  RV128I is not supported.
+The specification defines five base instruction sets: RV32I, RV32E, RV64I,
+RV64E, and RV128I. Currently, LLVM fully supports RV32I, and RV64I.  RV32E and
+RV64E are supported by the assembly-based tools only.  RV128I is not supported.
 
 To specify the target triple:
 
@@ -27,7 +27,7 @@ To specify the target triple:
      Architecture Description
      ============ ==============================================================
      ``riscv32``   RISC-V with XLEN=32 (i.e. RV32I or RV32E)
-     ``riscv64``   RISC-V with XLEN=64 (i.e. RV64I)
+     ``riscv64``   RISC-V with XLEN=64 (i.e. RV64I or RV64E)
      ============ ==============================================================
 
 To select an E variant ISA (e.g. RV32E instead of RV32I), use the base

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index d87d20704f166..525f57a90dfb0 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -144,6 +144,7 @@ Changes to the RISC-V Backend
 * Adds support for the vendor-defined XTHeadCmo (cache management operations) extension.
 * Adds support for the vendor-defined XTHeadSync (multi-core synchronization instructions) extension.
 * Added support for the vendor-defined XTHeadFMemIdx (indexed memory operations for floating point) extension.
+* Assembler support for RV64E was added.
 
 Changes to the WebAssembly Backend
 ----------------------------------

diff  --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 93cf66ff1f739..35c249a7b3703 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -584,8 +584,9 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
   bool HasRV64 = Arch.startswith("rv64");
   // ISA string must begin with rv32 or rv64.
   if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
-    return createStringError(errc::invalid_argument,
-                             "string must begin with rv32{i,e,g} or rv64{i,g}");
+    return createStringError(
+        errc::invalid_argument,
+        "string must begin with rv32{i,e,g} or rv64{i,e,g}");
   }
 
   unsigned XLen = HasRV64 ? 64 : 32;
@@ -601,14 +602,7 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
   default:
     return createStringError(errc::invalid_argument,
                              "first letter should be 'e', 'i' or 'g'");
-  case 'e': {
-    // Extension 'e' is not allowed in rv64.
-    if (HasRV64)
-      return createStringError(
-          errc::invalid_argument,
-          "standard user-level extension 'e' requires 'rv32'");
-    break;
-  }
+  case 'e':
   case 'i':
     break;
   case 'g':
@@ -828,8 +822,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
 }
 
 Error RISCVISAInfo::checkDependency() {
-  bool IsRv32 = XLen == 32;
-  bool HasE = Exts.count("e") != 0;
   bool HasD = Exts.count("d") != 0;
   bool HasF = Exts.count("f") != 0;
   bool HasZfinx = Exts.count("zfinx") != 0;
@@ -839,11 +831,6 @@ Error RISCVISAInfo::checkDependency() {
   bool HasZve64d = Exts.count("zve64d") != 0;
   bool HasZvl = MinVLen != 0;
 
-  if (HasE && !IsRv32)
-    return createStringError(
-        errc::invalid_argument,
-        "standard user-level extension 'e' requires 'rv32'");
-
   if (HasF && HasZfinx)
     return createStringError(errc::invalid_argument,
                              "'f' and 'zfinx' extensions are incompatible");
@@ -1115,6 +1102,8 @@ StringRef RISCVISAInfo::computeDefaultABI() const {
   } else if (XLen == 64) {
     if (hasExtension("d"))
       return "lp64d";
+    if (hasExtension("e"))
+      return "lp64e";
     return "lp64";
   }
   llvm_unreachable("Invalid XLEN");

diff  --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index d984f39321a6e..1627761052284 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -67,7 +67,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
 
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
   bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
-  bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); }
+  bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE); }
 
   RISCVTargetStreamer &getTargetStreamer() {
     assert(getParser().getStreamer().getTargetStreamer() &&
@@ -1352,9 +1352,9 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
 
 // Attempts to match Name as a register (either using the default name or
 // alternative ABI names), setting RegNo to the matching register. Upon
-// failure, returns true and sets RegNo to 0. If IsRV32E then registers
+// failure, returns true and sets RegNo to 0. If IsRVE then registers
 // x16-x31 will be rejected.
-static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo,
+static bool matchRegisterNameHelper(bool IsRVE, MCRegister &RegNo,
                                     StringRef Name) {
   RegNo = MatchRegisterName(Name);
   // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
@@ -1366,7 +1366,7 @@ static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo,
   static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
   if (RegNo == RISCV::NoRegister)
     RegNo = MatchRegisterAltName(Name);
-  if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
+  if (IsRVE && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
     RegNo = RISCV::NoRegister;
   return RegNo == RISCV::NoRegister;
 }
@@ -1387,7 +1387,7 @@ OperandMatchResultTy RISCVAsmParser::tryParseRegister(MCRegister &RegNo,
   RegNo = 0;
   StringRef Name = getLexer().getTok().getIdentifier();
 
-  if (matchRegisterNameHelper(isRV32E(), (MCRegister &)RegNo, Name))
+  if (matchRegisterNameHelper(isRVE(), (MCRegister &)RegNo, Name))
     return MatchOperand_NoMatch;
 
   getParser().Lex(); // Eat identifier token.
@@ -1420,7 +1420,7 @@ OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
   case AsmToken::Identifier:
     StringRef Name = getLexer().getTok().getIdentifier();
     MCRegister RegNo;
-    matchRegisterNameHelper(isRV32E(), RegNo, Name);
+    matchRegisterNameHelper(isRVE(), RegNo, Name);
 
     if (RegNo == RISCV::NoRegister) {
       if (HadParens)
@@ -1908,7 +1908,7 @@ OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
     return MatchOperand_ParseFail;
   }
   MCRegister RegNo;
-  matchRegisterNameHelper(isRV32E(), RegNo, Name);
+  matchRegisterNameHelper(isRVE(), RegNo, Name);
 
   if (RegNo == RISCV::NoRegister)
     return MatchOperand_NoMatch;
@@ -1927,7 +1927,7 @@ OperandMatchResultTy RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
 
   StringRef Name = getLexer().getTok().getIdentifier();
   MCRegister RegNo;
-  matchRegisterNameHelper(isRV32E(), RegNo, Name);
+  matchRegisterNameHelper(isRVE(), RegNo, Name);
 
   if (RegNo == RISCV::NoRegister)
     return MatchOperand_NoMatch;

diff  --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 15352c1c0885d..2d01d6df3a198 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -61,9 +61,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVDisassembler() {
 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
                                            uint64_t Address,
                                            const MCDisassembler *Decoder) {
-  bool IsRV32E = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureRV32E);
+  bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureRVE);
 
-  if (RegNo >= 32 || (IsRV32E && RegNo >= 16))
+  if (RegNo >= 32 || (IsRVE && RegNo >= 16))
     return MCDisassembler::Fail;
 
   MCRegister Reg = RISCV::X0 + RegNo;

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
index 98c8e883e5960..8f891a04def53 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -40,7 +40,7 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
                      StringRef ABIName) {
   auto TargetABI = getTargetABI(ABIName);
   bool IsRV64 = TT.isArch64Bit();
-  bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
+  bool IsRVE = FeatureBits[RISCV::FeatureRVE];
 
   if (!ABIName.empty() && TargetABI == ABI_Unknown) {
     errs()
@@ -54,11 +54,18 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
     errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
               "target-abi)\n";
     TargetABI = ABI_Unknown;
-  } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) {
+  } else if (!IsRV64 && IsRVE && TargetABI != ABI_ILP32E &&
+             TargetABI != ABI_Unknown) {
     // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
     errs()
         << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
     TargetABI = ABI_Unknown;
+  } else if (IsRV64 && IsRVE && TargetABI != ABI_LP64E &&
+             TargetABI != ABI_Unknown) {
+    // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
+    errs()
+        << "Only the lp64e ABI is supported for RV64E (ignoring target-abi)\n";
+    TargetABI = ABI_Unknown;
   }
 
   if (TargetABI != ABI_Unknown)
@@ -80,6 +87,7 @@ ABI getTargetABI(StringRef ABIName) {
                        .Case("lp64", ABI_LP64)
                        .Case("lp64f", ABI_LP64F)
                        .Case("lp64d", ABI_LP64D)
+                       .Case("lp64e", ABI_LP64E)
                        .Default(ABI_Unknown);
   return TargetABI;
 }
@@ -101,8 +109,6 @@ void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
     report_fatal_error("RV64 target requires an RV64 CPU");
   if (!TT.isArch64Bit() && !FeatureBits[RISCV::Feature32Bit])
     report_fatal_error("RV32 target requires an RV32 CPU");
-  if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E])
-    report_fatal_error("RV32E can't be enabled for an RV64 target");
   if (FeatureBits[RISCV::Feature32Bit] &&
       FeatureBits[RISCV::Feature64Bit])
     report_fatal_error("RV32 and RV64 can't be combined");

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 70fdc0e4ff120..175059fdf08e5 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -408,6 +408,7 @@ enum ABI {
   ABI_LP64,
   ABI_LP64F,
   ABI_LP64D,
+  ABI_LP64E,
   ABI_Unknown
 };
 

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index a05254b0ae579..356bb895c6ed4 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -103,6 +103,7 @@ void RISCVTargetELFStreamer::finish() {
     EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
     break;
   case RISCVABI::ABI_ILP32E:
+  case RISCVABI::ABI_LP64E:
     EFlags |= ELF::EF_RISCV_RVE;
     break;
   case RISCVABI::ABI_Unknown:

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index 756cc14a87014..f7bcc197b1872 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -47,10 +47,10 @@ void RISCVTargetStreamer::setTargetABI(RISCVABI::ABI ABI) {
 }
 
 void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
-  if (STI.hasFeature(RISCV::FeatureRV32E))
-    emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_4);
-  else
-    emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_16);
+  if (STI.hasFeature(RISCV::FeatureRVE))
+    report_fatal_error("Codegen not yet implemented for RVE");
+
+  emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_16);
 
   auto ParseResult = RISCVFeatures::parseFeatureBits(
       STI.hasFeature(RISCV::Feature64Bit), STI.getFeatureBits());

diff  --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index b0bb2992f6b42..0cf73bc37be84 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -589,11 +589,11 @@ def IsRV32 : Predicate<"!Subtarget->is64Bit()">,
 defvar RV32 = DefaultMode;
 def RV64           : HwMode<"+64bit", [IsRV64]>;
 
-def FeatureRV32E
-    : SubtargetFeature<"e", "IsRV32E", "true",
-                       "Implements RV32E (provides 16 rather than 32 GPRs)">;
-def IsRV32E : Predicate<"Subtarget->isRV32E()">,
-                        AssemblerPredicate<(all_of FeatureRV32E)>;
+def FeatureRVE
+    : SubtargetFeature<"e", "IsRVE", "true",
+                       "Implements RV{32,64}E (provides 16 rather than 32 GPRs)">;
+def IsRVE : Predicate<"Subtarget->isRVE()">,
+                        AssemblerPredicate<(all_of FeatureRVE)>;
 
 def FeatureRelax
     : SubtargetFeature<"relax", "EnableLinkerRelax", "true",

diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 595e094662f9a..9310c8161cd46 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -76,8 +76,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
                                          const RISCVSubtarget &STI)
     : TargetLowering(TM), Subtarget(STI) {
 
-  if (Subtarget.isRV32E())
-    report_fatal_error("Codegen not yet implemented for RV32E");
+  if (Subtarget.isRVE())
+    report_fatal_error("Codegen not yet implemented for RVE");
 
   RISCVABI::ABI ABI = Subtarget.getTargetABI();
   assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");

diff  --git a/llvm/test/CodeGen/RISCV/mattr-invalid-combination.ll b/llvm/test/CodeGen/RISCV/mattr-invalid-combination.ll
deleted file mode 100644
index e5bdb96fd0741..0000000000000
--- a/llvm/test/CodeGen/RISCV/mattr-invalid-combination.ll
+++ /dev/null
@@ -1,5 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: not --crash llc -mtriple=riscv64 -mattr=+e < %s 2>&1 \
-; RUN:   | FileCheck -check-prefix=RV64E %s
-
-; RV64E: LLVM ERROR: RV32E can't be enabled for an RV64 target

diff  --git a/llvm/test/CodeGen/RISCV/rv32e.ll b/llvm/test/CodeGen/RISCV/rv32e.ll
deleted file mode 100644
index 88379ab438725..0000000000000
--- a/llvm/test/CodeGen/RISCV/rv32e.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not --crash llc -mtriple=riscv32 -mattr=+e < %s 2>&1 | FileCheck %s
-
-; CHECK: LLVM ERROR: Codegen not yet implemented for RV32E
-
-define void @nothing() nounwind {
-  ret void
-}

diff  --git a/llvm/test/CodeGen/RISCV/rve.ll b/llvm/test/CodeGen/RISCV/rve.ll
new file mode 100644
index 0000000000000..29b9bab61f7ff
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rve.ll
@@ -0,0 +1,8 @@
+; RUN: not --crash llc -mtriple=riscv32 -mattr=+e < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc -mtriple=riscv64 -mattr=+e < %s 2>&1 | FileCheck %s
+
+; CHECK: LLVM ERROR: Codegen not yet implemented for RVE
+
+define void @nothing() nounwind {
+  ret void
+}

diff  --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s
index af0b3fe0cdc29..db1856e1c6677 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -1,7 +1,8 @@
 ## Arch string without version.
 
 # RUN: llvm-mc %s -triple=riscv32 -filetype=asm | FileCheck %s
-# RUN: llvm-mc %s -triple=riscv64 -filetype=asm | FileCheck %s
+# RUN: llvm-mc %s -triple=riscv64 -filetype=asm \
+# RUN:     | FileCheck --check-prefixes=CHECK,CHECK-RV64 %s
 
 .attribute arch, "rv32i"
 # CHECK: attribute      5, "rv32i2p0"
@@ -15,6 +16,9 @@
 .attribute arch, "rv32e"
 # CHECK: attribute      5, "rv32e2p0"
 
+.attribute arch, "rv64e"
+# CHECK-RV64: attribute      5, "rv64e2p0"
+
 .attribute arch, "rv32i2_m2"
 # CHECK: attribute      5, "rv32i2p0_m2p0"
 

diff  --git a/llvm/test/MC/RISCV/elf-flags.s b/llvm/test/MC/RISCV/elf-flags.s
index 543eadede1f70..546e129fb7194 100644
--- a/llvm/test/MC/RISCV/elf-flags.s
+++ b/llvm/test/MC/RISCV/elf-flags.s
@@ -5,6 +5,9 @@
 # RUN: llvm-mc -triple=riscv32 -mattr=+e -filetype=obj < %s \
 # RUN:   | llvm-readobj --file-headers - \
 # RUN:   | FileCheck -check-prefix=CHECK-RVE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+e -filetype=obj < %s \
+# RUN:   | llvm-readobj --file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-RVE %s
 # RUN: llvm-mc -triple=riscv32 -mattr=+experimental-ztso -filetype=obj < %s | llvm-readobj --file-headers - | FileCheck -check-prefixes=CHECK-TSO %s
 # RUN: llvm-mc -triple=riscv64 -mattr=+experimental-ztso -filetype=obj < %s | llvm-readobj --file-headers - | FileCheck -check-prefixes=CHECK-TSO %s
 

diff  --git a/llvm/test/MC/RISCV/invalid-attribute.s b/llvm/test/MC/RISCV/invalid-attribute.s
index 761a98902d5ef..3514452997266 100644
--- a/llvm/test/MC/RISCV/invalid-attribute.s
+++ b/llvm/test/MC/RISCV/invalid-attribute.s
@@ -7,7 +7,7 @@
 # RUN: not llvm-mc %s -triple=riscv64 -filetype=asm 2>&1 | FileCheck %s
 
 .attribute arch, "foo"
-# CHECK: [[@LINE-1]]:18: error: invalid arch name 'foo', string must begin with rv32{i,e,g} or rv64{i,g}
+# CHECK: [[@LINE-1]]:18: error: invalid arch name 'foo', string must begin with rv32{i,e,g} or rv64{i,e,g}
 
 .attribute arch, "rv32i2p0_y2p0"
 # CHECK: [[@LINE-1]]:18: error: invalid arch name 'rv32i2p0_y2p0', invalid standard user-level extension 'y'

diff  --git a/llvm/test/MC/RISCV/mattr-invalid-combination.s b/llvm/test/MC/RISCV/mattr-invalid-combination.s
deleted file mode 100644
index f75fd3723ed49..0000000000000
--- a/llvm/test/MC/RISCV/mattr-invalid-combination.s
+++ /dev/null
@@ -1,4 +0,0 @@
-# RUN: not --crash llvm-mc -triple riscv64 -mattr=+e < %s 2>&1 \
-# RUN:   | FileCheck %s -check-prefix=RV64E
-
-# RV64E: LLVM ERROR: RV32E can't be enabled for an RV64 target

diff  --git a/llvm/test/MC/RISCV/rv32e-invalid.s b/llvm/test/MC/RISCV/rv32e-invalid.s
index 760e7d49e5c46..9c19d3f40bcff 100644
--- a/llvm/test/MC/RISCV/rv32e-invalid.s
+++ b/llvm/test/MC/RISCV/rv32e-invalid.s
@@ -2,9 +2,13 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv32 < %s \
 # RUN:     | llvm-objdump --mattr=+e -M no-aliases -d -r - \
 # RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+# RUN: not llvm-mc -triple riscv64 -mattr=+e < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 < %s \
+# RUN:     | llvm-objdump --mattr=+e -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
 
 # Perform a simple check that registers x16-x31 (and the equivalent ABI names)
-# are rejected for RV32E, when both assembling and disassembling.
+# are rejected for RV32E/RV64E, when both assembling and disassembling.
 
 
 # CHECK-DIS: 37 18 00 00 <unknown>

diff  --git a/llvm/test/MC/RISCV/rv32e-valid.s b/llvm/test/MC/RISCV/rv32e-valid.s
index b0f435da50544..c2b77736d92b5 100644
--- a/llvm/test/MC/RISCV/rv32e-valid.s
+++ b/llvm/test/MC/RISCV/rv32e-valid.s
@@ -3,6 +3,11 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+e < %s \
 # RUN:     | llvm-objdump -M no-aliases -d -r - \
 # RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases -mattr=+e -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+e < %s \
+# RUN:     | llvm-objdump -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s
 
 # This file provides a basic test for RV32E, checking that the expected
 # set of registers and instructions are accepted.

diff  --git a/llvm/test/MC/RISCV/rv64e-valid.s b/llvm/test/MC/RISCV/rv64e-valid.s
new file mode 100644
index 0000000000000..4780fd6ece4ab
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64e-valid.s
@@ -0,0 +1,36 @@
+# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases -mattr=+e -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+e < %s \
+# RUN:     | llvm-objdump -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# This file provides a basic test for RV64E, checking that the expected
+# set of registers and instructions are accepted. It only tests instructions
+# that are not valid in RV32E.
+
+# CHECK-ASM-AND-OBJ: ld a4, 25(a5)
+ld x14, 25(x15)
+# CHECK-ASM-AND-OBJ: sd a2, 36(a3)
+sd a2, 36(a3)
+
+# CHECK-ASM-AND-OBJ: addiw a4, a5, 37
+addiw a4, a5, 37
+# CHECK-ASM-AND-OBJ: slliw t1, t1, 31
+slliw t1, t1, 31
+# CHECK-ASM-AND-OBJ: srliw a0, a4, 0
+srliw a0, a4, 0
+# CHECK-ASM-AND-OBJ: sraiw a1, sp, 15
+sraiw a1, sp, 15
+# CHECK-ASM-AND-OBJ: slliw t0, t1, 13
+slliw t0, t1, 13
+
+# CHECK-ASM-AND-OBJ: addw ra, zero, zero
+addw ra, zero, zero
+# CHECK-ASM-AND-OBJ: subw t0, t2, t1
+subw t0, t2, t1
+# CHECK-ASM-AND-OBJ: sllw a5, a4, a3
+sllw a5, a4, a3
+# CHECK-ASM-AND-OBJ: srlw a0, s0, t0
+srlw a0, s0, t0
+# CHECK-ASM-AND-OBJ: sraw t0, a3, zero
+sraw t0, a3, zero

diff  --git a/llvm/test/MC/RISCV/target-abi-invalid.s b/llvm/test/MC/RISCV/target-abi-invalid.s
index 20e9f89153e05..d7dba182fd166 100644
--- a/llvm/test/MC/RISCV/target-abi-invalid.s
+++ b/llvm/test/MC/RISCV/target-abi-invalid.s
@@ -32,6 +32,8 @@
 # RUN:   | FileCheck -check-prefix=RV32EF-LP64F %s
 # RUN: llvm-mc -triple=riscv32 -mattr=+e,+d -target-abi lp64f < %s 2>&1 \
 # RUN:   | FileCheck -check-prefix=RV32EFD-LP64D %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e -target-abi lp64e %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32E-LP64E %s
 
 # RV32I-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 # RV32IF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
@@ -39,6 +41,7 @@
 # RV32E-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 # RV32EF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 # RV32EFD-LP64D: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32E-LP64E: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 
 # RUN: llvm-mc -triple=riscv32 -target-abi ilp32f < %s 2>&1 \
 # RUN:   | FileCheck -check-prefix=RV32I-ILP32F %s
@@ -76,4 +79,18 @@
 # RV32EFD-ILP32F: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
 # RV32EFD-ILP32D: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
 
+# RUN: llvm-mc -triple=riscv64 -mattr=+e -target-abi lp64 < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64EF-LP64F %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+e,+f -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64EF-LP64F %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+e,+d -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64EFD-LP64F %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+e,+d -target-abi lp64d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64EFD-LP64D %s
+
+# RV64E-LP64: Only the lp64e ABI is supported for RV64E (ignoring target-abi)
+# RV64EF-LP64F: Only the lp64e ABI is supported for RV64E (ignoring target-abi)
+# RV64EFD-LP64F: Only the lp64e ABI is supported for RV64E (ignoring target-abi)
+# RV64EFD-LP64D: Only the lp64e ABI is supported for RV64E (ignoring target-abi)
+
 nop

diff  --git a/llvm/test/MC/RISCV/target-abi-valid.s b/llvm/test/MC/RISCV/target-abi-valid.s
index dab4420d0248c..63c0d4bf2e468 100644
--- a/llvm/test/MC/RISCV/target-abi-valid.s
+++ b/llvm/test/MC/RISCV/target-abi-valid.s
@@ -47,6 +47,10 @@
 # RUN:   | llvm-readobj --file-headers - \
 # RUN:   | FileCheck -check-prefix=CHECK-RVE %s
 
+# RUN: llvm-mc -triple=riscv64 -target-abi lp64e -filetype=obj < %s \
+# RUN:   | llvm-readobj --file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-RVE %s
+
 # CHECK-NONE:               Flags [ (0x0)
 # CHECK-NONE-NEXT:          ]
 

diff  --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp
index 0b749eb0c6815..05997d2d2d2c4 100644
--- a/llvm/unittests/Support/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp
@@ -109,7 +109,7 @@ TEST(ParseArchString, RejectsUpperCase) {
 TEST(ParseArchString, RejectsInvalidBaseISA) {
   for (StringRef Input : {"rv32", "rv64", "rv65i"}) {
     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
-              "string must begin with rv32{i,e,g} or rv64{i,g}");
+              "string must begin with rv32{i,e,g} or rv64{i,e,g}");
   }
   for (StringRef Input : {"rv32j", "rv64k", "rv32_i"}) {
     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
@@ -118,11 +118,9 @@ TEST(ParseArchString, RejectsInvalidBaseISA) {
 }
 
 TEST(ParseArchString, RejectsUnsupportedBaseISA) {
-  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64e", true).takeError()),
-            "standard user-level extension 'e' requires 'rv32'");
   for (StringRef Input : {"rv128i", "rv128g"}) {
     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
-              "string must begin with rv32{i,e,g} or rv64{i,g}");
+              "string must begin with rv32{i,e,g} or rv64{i,e,g}");
   }
 }
 
@@ -167,6 +165,15 @@ TEST(ParseArchString, AcceptsSupportedBaseISAsAndSetsXLenAndFLen) {
   EXPECT_EQ(InfoRV64I.getXLen(), 64U);
   EXPECT_EQ(InfoRV64I.getFLen(), 0U);
 
+  auto MaybeRV64E = RISCVISAInfo::parseArchString("rv64e", true);
+  ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
+  RISCVISAInfo &InfoRV64E = **MaybeRV64E;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV64E = InfoRV64E.getExtensions();
+  EXPECT_EQ(ExtsRV64E.size(), 1UL);
+  EXPECT_TRUE(ExtsRV64E.at("e") == (RISCVExtensionInfo{2, 0}));
+  EXPECT_EQ(InfoRV64E.getXLen(), 64U);
+  EXPECT_EQ(InfoRV64E.getFLen(), 0U);
+
   auto MaybeRV64G = RISCVISAInfo::parseArchString("rv64g", true);
   ASSERT_THAT_EXPECTED(MaybeRV64G, Succeeded());
   RISCVISAInfo &InfoRV64G = **MaybeRV64G;


        


More information about the cfe-commits mailing list