diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c --- 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 --- 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 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -15,9 +15,9 @@ 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 @@ 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 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -144,6 +144,7 @@ * 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 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -584,8 +584,9 @@ 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 @@ 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 @@ } 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 @@ 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 @@ } 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 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -67,7 +67,7 @@ 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 @@ // 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_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 @@ 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 @@ 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 @@ return MatchOperand_ParseFail; } MCRegister RegNo; - matchRegisterNameHelper(isRV32E(), RegNo, Name); + matchRegisterNameHelper(isRVE(), RegNo, Name); if (RegNo == RISCV::NoRegister) return MatchOperand_NoMatch; @@ -1927,7 +1927,7 @@ 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 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -61,9 +61,9 @@ 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.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -408,6 +408,7 @@ ABI_LP64, ABI_LP64F, ABI_LP64D, + ABI_LP64E, ABI_Unknown }; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -40,7 +40,7 @@ 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 @@ 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 @@ .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 @@ 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/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -103,6 +103,7 @@ 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 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -47,10 +47,10 @@ } 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 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -589,11 +589,11 @@ 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 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -76,8 +76,8 @@ 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 --- 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 --- 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 --- /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 --- 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 --- 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 --- 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 --- 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 --- 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 diff --git a/llvm/test/MC/RISCV/rv32e-valid.s b/llvm/test/MC/RISCV/rv32e-valid.s --- 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 --- /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 --- 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 --- 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 --- a/llvm/unittests/Support/RISCVISAInfoTest.cpp +++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp @@ -109,7 +109,7 @@ 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, 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 @@ 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;