https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/139369
>From 27d19726f348c07de1e3437ef93511ff21fff8bb Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Sat, 10 May 2025 18:01:57 +0800 Subject: [PATCH] [RISCV][MC] Add support for Q extension --- .../Driver/print-supported-extensions-riscv.c | 1 + clang/test/Driver/riscv-arch.c | 26 ++- .../test/Preprocessor/riscv-target-features.c | 12 ++ llvm/docs/RISCVUsage.rst | 1 + .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 22 ++- .../RISCV/Disassembler/RISCVDisassembler.cpp | 11 ++ llvm/lib/Target/RISCV/RISCVFeatures.td | 7 + llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 13 ++ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 1 + llvm/lib/Target/RISCV/RISCVInstrInfoD.td | 6 +- llvm/lib/Target/RISCV/RISCVInstrInfoF.td | 8 +- llvm/lib/Target/RISCV/RISCVInstrInfoQ.td | 171 ++++++++++++++++ llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td | 20 +- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 3 + llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 21 ++ llvm/lib/Target/RISCV/RISCVSchedGenericOOO.td | 1 + llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td | 1 + llvm/lib/Target/RISCV/RISCVSchedRocket.td | 1 + llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 1 + llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td | 1 + llvm/lib/Target/RISCV/RISCVSchedSiFiveP500.td | 1 + llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 1 + .../lib/Target/RISCV/RISCVSchedSpacemitX60.td | 1 + .../Target/RISCV/RISCVSchedSyntacoreSCR345.td | 1 + .../Target/RISCV/RISCVSchedSyntacoreSCR7.td | 1 + .../lib/Target/RISCV/RISCVSchedTTAscalonD8.td | 1 + .../Target/RISCV/RISCVSchedXiangShanNanHu.td | 1 + llvm/lib/Target/RISCV/RISCVSchedule.td | 88 ++++++++- llvm/lib/Target/RISCV/RISCVSubtarget.h | 3 + llvm/lib/TargetParser/RISCVISAInfo.cpp | 5 +- llvm/test/CodeGen/RISCV/attributes.ll | 4 + llvm/test/CodeGen/RISCV/features-info.ll | 1 + llvm/test/MC/RISCV/rv32q-invalid.s | 21 ++ llvm/test/MC/RISCV/rv64q-invalid.s | 9 + llvm/test/MC/RISCV/rv64q-valid.s | 43 ++++ llvm/test/MC/RISCV/rvq-aliases-valid.s | 55 ++++++ llvm/test/MC/RISCV/rvq-pseudos.s | 12 ++ llvm/test/MC/RISCV/rvq-valid.s | 184 ++++++++++++++++++ .../TargetParser/RISCVISAInfoTest.cpp | 1 + 39 files changed, 728 insertions(+), 33 deletions(-) create mode 100644 llvm/lib/Target/RISCV/RISCVInstrInfoQ.td create mode 100644 llvm/test/MC/RISCV/rv32q-invalid.s create mode 100644 llvm/test/MC/RISCV/rv64q-invalid.s create mode 100644 llvm/test/MC/RISCV/rv64q-valid.s create mode 100644 llvm/test/MC/RISCV/rvq-aliases-valid.s create mode 100644 llvm/test/MC/RISCV/rvq-pseudos.s create mode 100644 llvm/test/MC/RISCV/rvq-valid.s diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index b10850aadddc3..cbadb86f006f4 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -10,6 +10,7 @@ // CHECK-NEXT: a 2.1 'A' (Atomic Instructions) // CHECK-NEXT: f 2.2 'F' (Single-Precision Floating-Point) // CHECK-NEXT: d 2.2 'D' (Double-Precision Floating-Point) +// CHECK-NEXT: q 2.2 'Q' (Quad-Precision Floating-Point) // CHECK-NEXT: c 2.0 'C' (Compressed Instructions) // CHECK-NEXT: b 1.0 'B' (the collection of the Zba, Zbb, Zbs extensions) // CHECK-NEXT: v 1.0 'V' (Vector Extension for Application Processors) diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 018fa25218ea6..32e7c0d44b243 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -10,6 +10,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32imafd -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv32imafdq -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32ic -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -21,6 +23,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32imafdc -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv32imafdqc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32ia -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -28,6 +32,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32iafd -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv32iafdq -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32iac -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -35,6 +41,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32iafdc -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv32iafdqc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv32-unknown-elf -march=rv32g -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -80,6 +88,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64imafd -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv64imafdq -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64ic -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -91,6 +101,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64imafdc -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv32-unknown-elf -march=rv64imafdqc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64ia -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -98,6 +110,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64iafd -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv64-unknown-elf -march=rv64iafdq -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64iac -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -105,6 +119,8 @@ // RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64iafdc -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang --target=riscv64-unknown-elf -march=rv64iafdqc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -march=rv64g -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck %s @@ -211,11 +227,6 @@ // RV32-LETTER: error: invalid arch name 'rv32q', // RV32-LETTER: first letter after 'rv32' should be 'e', 'i' or 'g' -// RUN: not %clang --target=riscv32-unknown-elf -march=rv32imcq -### %s \ -// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ORDER %s -// RV32-ORDER: error: invalid arch name 'rv32imcq', -// RV32-ORDER: unsupported standard user-level extension 'q' - // RUN: not %clang --target=riscv32-unknown-elf -march=rv32izvl64b -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZVL64B-ER %s // RV32-ZVL64B-ER: error: invalid arch name 'rv32izvl64b', @@ -226,11 +237,6 @@ // RV32-STD-INVAL: error: invalid arch name 'rv32imw', // RV32-STD-INVAL: invalid standard user-level extension 'w' -// RUN: not %clang --target=riscv32-unknown-elf -march=rv32imqc -### %s \ -// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD %s -// RV32-STD: error: invalid arch name 'rv32imqc', -// RV32-STD: unsupported standard user-level extension 'q' - // RUN: not %clang --target=riscv32-unknown-elf -march=rv32xabc -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X %s // RV32X: error: invalid arch name 'rv32xabc', diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 25f15cc5283f9..e3b456e0245f7 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -20,6 +20,7 @@ // CHECK-NOT: __riscv_m {{.*$}} // CHECK-NOT: __riscv_mul {{.*$}} // CHECK-NOT: __riscv_muldiv {{.*$}} +// CHECK-NOT: __riscv_q {{.*$}} // CHECK-NOT: __riscv_sha {{.*$}} // CHECK-NOT: __riscv_shcounterenw {{.*$}} // CHECK-NOT: __riscv_shgatpa {{.*$}} @@ -334,6 +335,17 @@ // CHECK-M-EXT: __riscv_mul 1 // CHECK-M-EXT: __riscv_muldiv 1 +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ifdq -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-Q-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ifdq -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-Q-EXT %s +// CHECK-Q-EXT: __riscv_fdiv 1 +// CHECK-Q-EXT: __riscv_flen 128 +// CHECK-Q-EXT: __riscv_fsqrt 1 +// CHECK-Q-EXT: __riscv_q 2002000{{$}} + // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32isha -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-SHCOUNTERENW-EXT %s diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 4b98f58304f13..8aec0f80cf0ed 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -119,6 +119,7 @@ on support follow. ``E`` Supported (`See note <#riscv-rve-note>`__) ``H`` Assembly Support ``M`` Supported + ``Q`` Assembly Support ``Sha`` Supported ``Shcounterenw`` Assembly Support (`See note <#riscv-profiles-extensions-note>`__) ``Shgatpa`` Assembly Support (`See note <#riscv-profiles-extensions-note>`__) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 9bc4734815364..a1c9091c95b48 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -1272,6 +1272,11 @@ static MCRegister convertFPR64ToFPR32(MCRegister Reg) { return Reg - RISCV::F0_D + RISCV::F0_F; } +static MCRegister convertFPR64ToFPR128(MCRegister Reg) { + assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register"); + return Reg - RISCV::F0_D + RISCV::F0_Q; +} + static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, unsigned Kind) { unsigned RegClassID; @@ -1300,6 +1305,10 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg); bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg); + if (IsRegFPR64 && Kind == MCK_FPR128) { + Op.Reg.RegNum = convertFPR64ToFPR128(Reg); + return Match_Success; + } // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary. if ((IsRegFPR64 && Kind == MCK_FPR32) || @@ -1663,13 +1672,16 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // rejected. MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const { MCRegister Reg = MatchRegisterName(Name); - // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial - // match always matches the 64-bit variant, and not the 16/32-bit one. + // The 16-/32-/128- and 64-bit FPRs have the same asm name. Check + // that the initial match always matches the 64-bit variant, and + // not the 16/32/128-bit one. assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H)); assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F)); + assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q)); // The default FPR register class is based on the tablegen enum ordering. static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated"); static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated"); + static_assert(RISCV::F0_D < RISCV::F0_Q, "FPR matching must be updated"); if (!Reg) Reg = MatchRegisterAltName(Name); if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31) @@ -3848,6 +3860,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case RISCV::PseudoFLD: emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true); return false; + case RISCV::PseudoFLQ: + emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true); + return false; case RISCV::PseudoSB: case RISCV::PseudoQC_E_SB: emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true); @@ -3875,6 +3890,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case RISCV::PseudoFSD: emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); return false; + case RISCV::PseudoFSQ: + emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true); + return false; case RISCV::PseudoAddTPRel: if (checkPseudoAddTPRel(Inst, Operands)) return true; diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index 8f1b790826b24..5eb60070f391f 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -177,6 +177,17 @@ static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint32_t RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeFPR128RegisterClass(MCInst &Inst, uint32_t RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + if (RegNo >= 32) + return MCDisassembler::Fail; + + MCRegister Reg = RISCV::F0_Q + RegNo; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 18d341aa5b5ca..c26f5aae7ab26 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -291,6 +291,13 @@ def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">, AssemblerPredicate<(all_of FeatureStdExtD), "'D' (Double-Precision Floating-Point)">; +def FeatureStdExtQ + : RISCVExtension<2, 2, "Quad-Precision Floating-Point", [FeatureStdExtD]>, + RISCVExtensionBitmask<0, 16>; +def HasStdExtQ : Predicate<"Subtarget->hasStdExtQ()">, + AssemblerPredicate<(all_of FeatureStdExtQ), + "'Q' (Quad-Precision Floating-Point)">; + def FeatureStdExtZfhmin : RISCVExtension<1, 0, "Half-Precision Floating-Point Minimal", [FeatureStdExtF]>, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index f181c1e137545..bc6f77d95e0bb 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -599,6 +599,13 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } + if (RISCV::FPR128RegClass.contains(DstReg, SrcReg)) { + BuildMI(MBB, MBBI, DL, get(RISCV::FSGNJ_Q), DstReg) + .addReg(SrcReg, getKillRegState(KillSrc)) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + if (RISCV::FPR32RegClass.contains(DstReg) && RISCV::GPRRegClass.contains(SrcReg)) { BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg) @@ -674,6 +681,9 @@ void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) { Opcode = RISCV::FSD; IsScalableVector = false; + } else if (RISCV::FPR128RegClass.hasSubClassEq(RC)) { + Opcode = RISCV::FSQ; + IsScalableVector = false; } else if (RISCV::VRRegClass.hasSubClassEq(RC)) { Opcode = RISCV::VS1R_V; } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) { @@ -766,6 +776,9 @@ void RISCVInstrInfo::loadRegFromStackSlot( } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) { Opcode = RISCV::FLD; IsScalableVector = false; + } else if (RISCV::FPR128RegClass.hasSubClassEq(RC)) { + Opcode = RISCV::FLQ; + IsScalableVector = false; } else if (RISCV::VRRegClass.hasSubClassEq(RC)) { Opcode = RISCV::VL1RE8_V; } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index e9bdeb88e4ca8..3f6931b584c16 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -2213,6 +2213,7 @@ include "RISCVInstrInfoZalasr.td" // Scalar FP include "RISCVInstrInfoF.td" include "RISCVInstrInfoD.td" +include "RISCVInstrInfoQ.td" include "RISCVInstrInfoZfh.td" include "RISCVInstrInfoZfbfmin.td" include "RISCVInstrInfoZfa.td" diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td index 0c584daf45b14..c83976ab714af 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -58,12 +58,12 @@ def FPR64IN32X : RegisterOperand<GPRPair> { let ParserMatchClass = GPRPairAsFPR; } -def DExt : ExtInfo<"", "", [HasStdExtD], f64, FPR64, FPR32, FPR64, ?>; +def DExt : ExtInfo<"", "", [HasStdExtD], f64, FPR64, FPR32, FPR64, ?, ?>; def ZdinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZdinx, IsRV64], - f64, FPR64INX, FPR32INX, FPR64INX, ?>; + f64, FPR64INX, FPR32INX, FPR64INX, ?, ?>; def Zdinx32Ext : ExtInfo<"_IN32X", "ZdinxRV32Only", [HasStdExtZdinx, IsRV32], - f64, FPR64IN32X, FPR32INX, FPR64IN32X, ?>; + f64, FPR64IN32X, FPR32INX, FPR64IN32X, ?, ?>; defvar DExts = [DExt, ZdinxExt, Zdinx32Ext]; defvar DExtsRV64 = [DExt, ZdinxExt]; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td index 360191f03ddf7..69987ef251920 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -131,7 +131,7 @@ def FPR32INX : RegisterOperand<GPRF32> { // The DAGOperand can be unset if the predicates are not enough to define it. class ExtInfo<string suffix, string space, list<Predicate> predicates, ValueType primaryvt, DAGOperand primaryty, DAGOperand f32ty, - DAGOperand f64ty, DAGOperand f16ty> { + DAGOperand f64ty, DAGOperand f16ty, DAGOperand f128ty> { list<Predicate> Predicates = predicates; string Suffix = suffix; string Space = space; @@ -139,12 +139,14 @@ class ExtInfo<string suffix, string space, list<Predicate> predicates, DAGOperand F16Ty = f16ty; DAGOperand F32Ty = f32ty; DAGOperand F64Ty = f64ty; + DAGOperand F128Ty = f128ty; ValueType PrimaryVT = primaryvt; } -def FExt : ExtInfo<"", "", [HasStdExtF], f32, FPR32, FPR32, ?, ?>; +def FExt : ExtInfo<"", "", [HasStdExtF], f32, FPR32, FPR32, ?, ?, ?>; -def ZfinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZfinx], f32, FPR32INX, FPR32INX, ?, ?>; +def ZfinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZfinx], f32, FPR32INX, + FPR32INX, ?, ?, ?>; defvar FExts = [FExt, ZfinxExt]; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td b/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td new file mode 100644 index 0000000000000..5fc4f7c0a775f --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td @@ -0,0 +1,171 @@ +//===-- RISCVInstrInfoQ.td - RISC-V 'Q' instructions -------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the RISC-V instructions from the standard 'Q', +// Quad-Precision Floating-Point instruction set extension. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Operand and SDNode transformation definitions. +//===----------------------------------------------------------------------===// + +def QExt : ExtInfo<"", "", [HasStdExtQ], f128, FPR128, FPR32, FPR64, ?, FPR128>; + +defvar QExts = [QExt]; +defvar QExtsRV64 = [QExt]; + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Predicates = [HasStdExtQ] in { + def FLQ : FPLoad_r<0b100, "flq", FPR128, WriteFLD128>; + + // Operands for stores are in the order srcreg, base, offset rather than + // reflecting the order these fields are specified in the instruction + // encoding. + def FSQ : FPStore_r<0b100, "fsq", FPR128, WriteFST128>; +} // Predicates = [HasStdExtQ] + +foreach Ext = QExts in { + let SchedRW = [WriteFMA128, ReadFMA128, ReadFMA128, ReadFMA128Addend] in { + defm FMADD_Q : FPFMA_rrr_frm_m<OPC_MADD, 0b11, "fmadd.q", Ext>; + defm FMSUB_Q : FPFMA_rrr_frm_m<OPC_MSUB, 0b11, "fmsub.q", Ext>; + defm FNMSUB_Q : FPFMA_rrr_frm_m<OPC_NMSUB, 0b11, "fnmsub.q", Ext>; + defm FNMADD_Q : FPFMA_rrr_frm_m<OPC_NMADD, 0b11, "fnmadd.q", Ext>; + } + + let SchedRW = [WriteFAdd128, ReadFAdd128, ReadFAdd128] in { + defm FADD_Q : FPALU_rr_frm_m<0b0000011, "fadd.q", Ext>; + defm FSUB_Q : FPALU_rr_frm_m<0b0000111, "fsub.q", Ext>; + } + + let SchedRW = [WriteFMul128, ReadFMul128, ReadFMul128] in + defm FMUL_Q : FPALU_rr_frm_m<0b0001011, "fmul.q", Ext>; + + let SchedRW = [WriteFDiv128, ReadFDiv128, ReadFDiv128] in + defm FDIV_Q : FPALU_rr_frm_m<0b0001111, "fdiv.q", Ext>; + + defm FSQRT_Q : FPUnaryOp_r_frm_m<0b0101111, 0b00000, Ext, Ext.PrimaryTy, + Ext.PrimaryTy, "fsqrt.q">, + Sched<[WriteFSqrt128, ReadFSqrt128]>; + + let SchedRW = [WriteFSGNJ128, ReadFSGNJ128, ReadFSGNJ128], + mayRaiseFPException = 0 in { + defm FSGNJ_Q : FPALU_rr_m<0b0010011, 0b000, "fsgnj.q", Ext>; + defm FSGNJN_Q : FPALU_rr_m<0b0010011, 0b001, "fsgnjn.q", Ext>; + defm FSGNJX_Q : FPALU_rr_m<0b0010011, 0b010, "fsgnjx.q", Ext>; + } + + let SchedRW = [WriteFMinMax128, ReadFMinMax128, ReadFMinMax128] in { + defm FMIN_Q : FPALU_rr_m<0b0010111, 0b000, "fmin.q", Ext, Commutable = 1>; + defm FMAX_Q : FPALU_rr_m<0b0010111, 0b001, "fmax.q", Ext, Commutable = 1>; + } + + defm FCVT_S_Q : FPUnaryOp_r_frm_m<0b0100000, 0b00011, Ext, Ext.F32Ty, + Ext.PrimaryTy, "fcvt.s.q">, + Sched<[WriteFCvtF128ToF32, ReadFCvtF128ToF32]>; + + defm FCVT_Q_S : FPUnaryOp_r_frmlegacy_m<0b0100011, 0b00000, Ext, + Ext.PrimaryTy, Ext.F32Ty, "fcvt.q.s">, + Sched<[WriteFCvtF32ToF128, ReadFCvtF32ToF128]>; + + defm FCVT_D_Q : FPUnaryOp_r_frm_m<0b0100001, 0b00011, Ext, Ext.F64Ty, + Ext.PrimaryTy, "fcvt.d.q">, + Sched<[WriteFCvtF128ToF64, ReadFCvtF128ToF64]>; + + defm FCVT_Q_D : FPUnaryOp_r_frmlegacy_m<0b0100011, 0b00001, Ext, + Ext.PrimaryTy, Ext.F64Ty, "fcvt.q.d">, + Sched<[WriteFCvtF64ToF128, ReadFCvtF64ToF128]>; + + let SchedRW = [WriteFCmp128, ReadFCmp128, ReadFCmp128] in { + defm FEQ_Q : FPCmp_rr_m<0b1010011, 0b010, "feq.q", Ext, Commutable = 1>; + defm FLT_Q : FPCmp_rr_m<0b1010011, 0b001, "flt.q", Ext>; + defm FLE_Q : FPCmp_rr_m<0b1010011, 0b000, "fle.q", Ext>; + } + + let mayRaiseFPException = 0 in + defm FCLASS_Q : FPUnaryOp_r_m<0b1110011, 0b00000, 0b001, Ext, GPR, + Ext.PrimaryTy, "fclass.q">, + Sched<[WriteFClass128, ReadFClass128]>; + + let IsSignExtendingOpW = 1 in + defm FCVT_W_Q : FPUnaryOp_r_frm_m<0b1100011, 0b00000, Ext, GPR, + Ext.PrimaryTy, "fcvt.w.q">, + Sched<[WriteFCvtF128ToI32, ReadFCvtF128ToI32]>; + + let IsSignExtendingOpW = 1 in + defm FCVT_WU_Q : FPUnaryOp_r_frm_m<0b1100011, 0b00001, Ext, GPR, + Ext.PrimaryTy, "fcvt.wu.q">, + Sched<[WriteFCvtF128ToI32, ReadFCvtF128ToI32]>; + + let mayRaiseFPException = 0 in + defm FCVT_Q_W : FPUnaryOp_r_frmlegacy_m<0b1101011, 0b00000, Ext, + Ext.PrimaryTy, GPR, "fcvt.q.w">, + Sched<[WriteFCvtI32ToF128, ReadFCvtI32ToF128]>; + + let mayRaiseFPException = 0 in + defm FCVT_Q_WU : FPUnaryOp_r_frmlegacy_m<0b1101011, 0b00001, Ext, + Ext.PrimaryTy, GPR, "fcvt.q.wu">, + Sched<[WriteFCvtI32ToF128, ReadFCvtI32ToF128]>; +} // foreach Ext = QExts + +foreach Ext = QExtsRV64 in { + defm FCVT_L_Q : FPUnaryOp_r_frm_m<0b1100011, 0b00010, Ext, GPR, Ext.PrimaryTy, + "fcvt.l.q", [IsRV64]>, + Sched<[WriteFCvtF128ToI64, ReadFCvtF128ToI64]>; + + defm FCVT_LU_Q : FPUnaryOp_r_frm_m<0b1100011, 0b00011, Ext, GPR, + Ext.PrimaryTy, "fcvt.lu.q", [IsRV64]>, + Sched<[WriteFCvtF128ToI64, ReadFCvtF128ToI64]>; + + let mayRaiseFPException = 0 in + defm FCVT_Q_L : FPUnaryOp_r_frmlegacy_m<0b1101011, 0b00010, Ext, Ext.PrimaryTy, + GPR, "fcvt.q.l", [IsRV64]>, + Sched<[WriteFCvtI64ToF128, ReadFCvtI64ToF128]>; + + let mayRaiseFPException = 0 in + defm FCVT_Q_LU : FPUnaryOp_r_frmlegacy_m<0b1101011, 0b00011, Ext, Ext.PrimaryTy, + GPR, "fcvt.q.lu", [IsRV64]>, + Sched<[WriteFCvtI64ToF128, ReadFCvtI64ToF128]>; +} // foreach Ext = QExtsRV64 + +//===----------------------------------------------------------------------===// +// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) +//===----------------------------------------------------------------------===// + +let Predicates = [HasStdExtQ] in { + def : InstAlias<"flq $rd, (${rs1})", (FLQ FPR128:$rd, GPR:$rs1, 0), 0>; + def : InstAlias<"fsq $rs2, (${rs1})", (FSQ FPR128:$rs2, GPR:$rs1, 0), 0>; + + def : InstAlias<"fmv.q $rd, $rs", (FSGNJ_Q FPR128:$rd, FPR128:$rs, + FPR128:$rs)>; + def : InstAlias<"fabs.q $rd, $rs", (FSGNJX_Q FPR128:$rd, FPR128:$rs, + FPR128:$rs)>; + def : InstAlias<"fneg.q $rd, $rs", (FSGNJN_Q FPR128:$rd, FPR128:$rs, + FPR128:$rs)>; + + // fgt.q/fge.q are recognised by the GNU assembler but the canonical + // flt.q/fle.q forms will always be printed. Therefore, set a zero weight. + def : InstAlias<"fgt.q $rd, $rs, $rt", + (FLT_Q GPR:$rd, FPR128:$rt, FPR128:$rs), 0>; + def : InstAlias<"fge.q $rd, $rs, $rt", + (FLE_Q GPR:$rd, FPR128:$rt, FPR128:$rs), 0>; + + def PseudoFLQ : PseudoFloatLoad<"flq", FPR128>; + def PseudoFSQ : PseudoStore<"fsq", FPR128>; +} // Predicates = [HasStdExtQ] + +let Predicates = [HasStdExtQ] in { +/// Loads +def : LdPat<load, FLQ, f128>; + +/// Stores +def : StPat<store, FSQ, FPR128, f128>; +} // Predicates = [HasStdExtQ] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td index 7c7e106e868c1..8c11bf082c98b 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -53,32 +53,32 @@ def FPR16INX : RegisterOperand<GPRF16> { } def ZfhExt : ExtInfo<"", "", [HasStdExtZfh], - f16, FPR16, FPR32, ?, FPR16>; + f16, FPR16, FPR32, ?, FPR16, ?>; def ZfhminExt : ExtInfo<"", "", [HasStdExtZfhmin], - f16, FPR16, FPR32, ?, FPR16>; + f16, FPR16, FPR32, ?, FPR16, ?>; def ZfhDExt : ExtInfo<"", "", [HasStdExtZfh, HasStdExtD], - ?, ?, FPR32, FPR64, FPR16>; + ?, ?, FPR32, FPR64, FPR16, ?>; def ZfhminDExt : ExtInfo<"", "", [HasStdExtZfhmin, HasStdExtD], - ?, ?, FPR32, FPR64, FPR16>; + ?, ?, FPR32, FPR64, FPR16, ?>; def ZhinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZhinx], - f16, FPR16INX, FPR32INX, ?, FPR16INX>; + f16, FPR16INX, FPR32INX, ?, FPR16INX, ?>; def ZhinxminExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZhinxmin], - f16, FPR16INX, FPR32INX, ?, FPR16INX>; + f16, FPR16INX, FPR32INX, ?, FPR16INX, ?>; def ZhinxZdinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZhinx, HasStdExtZdinx, IsRV64], - ?, ?, FPR32INX, FPR64INX, FPR16INX>; + ?, ?, FPR32INX, FPR64INX, FPR16INX, ?>; def ZhinxminZdinxExt : ExtInfo<"_INX", "Zfinx", [HasStdExtZhinxmin, HasStdExtZdinx, IsRV64], - ?, ?, FPR32INX, FPR64INX, FPR16INX>; + ?, ?, FPR32INX, FPR64INX, FPR16INX, ?>; def ZhinxZdinx32Ext : ExtInfo<"_IN32X", "ZdinxGPRPairRV32", [HasStdExtZhinx, HasStdExtZdinx, IsRV32], - ?, ?, FPR32INX, FPR64IN32X, FPR16INX >; + ?, ?, FPR32INX, FPR64IN32X, FPR16INX, ?>; def ZhinxminZdinx32Ext : ExtInfo<"_IN32X", "ZdinxGPRPairRV32", [HasStdExtZhinxmin, HasStdExtZdinx, IsRV32], - ?, ?, FPR32INX, FPR64IN32X, FPR16INX>; + ?, ?, FPR32INX, FPR64IN32X, FPR16INX, ?>; defvar ZfhExts = [ZfhExt, ZhinxExt]; defvar ZfhminExts = [ZfhminExt, ZhinxminExt]; diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index c6f6c9007b2b1..65a6f54d6c8aa 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -48,6 +48,9 @@ static_assert(RISCV::F31_F == RISCV::F0_F + 31, static_assert(RISCV::F1_D == RISCV::F0_D + 1, "Register list not consecutive"); static_assert(RISCV::F31_D == RISCV::F0_D + 31, "Register list not consecutive"); +static_assert(RISCV::F1_Q == RISCV::F0_Q + 1, "Register list not consecutive"); +static_assert(RISCV::F31_Q == RISCV::F0_Q + 31, + "Register list not consecutive"); static_assert(RISCV::V1 == RISCV::V0 + 1, "Register list not consecutive"); static_assert(RISCV::V31 == RISCV::V0 + 31, "Register list not consecutive"); diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index eb3d5e553f1ef..cd725ca6166e2 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -45,6 +45,13 @@ class RISCVReg64<RISCVReg32 subreg> let SubRegIndices = [sub_32]; } +def sub_64 : SubRegIndex<64>; +class RISCVReg128<RISCVReg64 subreg> + : RISCVRegWithSubRegs<subreg.HWEncoding{4-0}, subreg.AsmName, [subreg], + subreg.AltNames> { + let SubRegIndices = [sub_64]; +} + let FallbackRegAltNameIndex = NoRegAltName in def ABIRegAltName : RegAltNameIndex; @@ -412,6 +419,11 @@ let RegAltNameIndices = [ABIRegAltName] in { def F#Index#_D : RISCVReg64<!cast<RISCVReg32>("F"#Index#"_F")>, DwarfRegAlias<!cast<Register>("F"#Index#"_H")>; } + + foreach Index = 0-31 in { + def F#Index#_Q : RISCVReg128<!cast<RISCVReg64>("F"#Index#"_D")>, + DwarfRegAlias<!cast<Register>("F"#Index#"_H")>; + } } // The order of registers represents the preferred allocation sequence, @@ -462,6 +474,15 @@ def FPR64C : RISCVRegisterClass<[f64], 64, (add (sequence "F%u_D", 8, 9) )>; +def FPR128 : RISCVRegisterClass<[f128], 128, (add + (sequence "F%u_Q", 15, 10), + (sequence "F%u_Q", 0, 7), + (sequence "F%u_Q", 16, 17), + (sequence "F%u_Q", 28, 31), + (sequence "F%u_Q", 8, 9), + (sequence "F%u_Q", 18, 27) +)>; + //===----------------------------------------------------------------------===// // GPR Classes for "H/F/D in X" //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVSchedGenericOOO.td b/llvm/lib/Target/RISCV/RISCVSchedGenericOOO.td index be9c4ddf7cf48..248d2273ef2f4 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedGenericOOO.td +++ b/llvm/lib/Target/RISCV/RISCVSchedGenericOOO.td @@ -492,6 +492,7 @@ def : ReadAdvance<ReadFSqrt16, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions //===----------------------------------------------------------------------===// +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedZvk; defm : UnsupportedSchedSFB; diff --git a/llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td b/llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td index a1127966e8417..8ba4cd0acdd6c 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td +++ b/llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td @@ -263,6 +263,7 @@ def : ReadAdvance<ReadIRem, 0>; def : ReadAdvance<ReadIRem32, 0>; // Unsupported extensions. +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedZbc; defm : UnsupportedSchedZbs; diff --git a/llvm/lib/Target/RISCV/RISCVSchedRocket.td b/llvm/lib/Target/RISCV/RISCVSchedRocket.td index 1148581415380..4c4654ba2fc0f 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedRocket.td +++ b/llvm/lib/Target/RISCV/RISCVSchedRocket.td @@ -250,6 +250,7 @@ def : ReadAdvance<ReadFClass64, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedZabha; defm : UnsupportedSchedZba; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index f4d2073d3b52d..af64a871a9292 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -1300,6 +1300,7 @@ foreach mx = SchedMxList in { //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedZabha; defm : UnsupportedSchedZbc; defm : UnsupportedSchedZbkb; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td index 1ac05c9444725..370ea64699383 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td @@ -1231,6 +1231,7 @@ defm "" : LMULReadAdvance<"ReadVSM3MEV", 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedZabha; defm : UnsupportedSchedZbc; defm : UnsupportedSchedZbkb; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP500.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP500.td index ca116e0c54f3f..5933d73174f79 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP500.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP500.td @@ -348,6 +348,7 @@ def : ReadAdvance<ReadSHXADD32, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedZabha; defm : UnsupportedSchedZbc; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 2bfd5ef811c7b..7c04d1c54473d 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -1487,6 +1487,7 @@ defm "" : LMULReadAdvance<"ReadVSM3MEV", 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedZabha; defm : UnsupportedSchedZbc; defm : UnsupportedSchedZbkb; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index c21ab969d12ac..8948694c420a0 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -342,6 +342,7 @@ def : ReadAdvance<ReadSingleBitImm, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedXsfvcp; defm : UnsupportedSchedZabha; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td b/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td index e509abc9f922e..815c2da992a11 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td @@ -199,6 +199,7 @@ multiclass SCR3_Unsupported : multiclass SCR4_SCR5_Unsupported : SCR_Unsupported, + UnsupportedSchedQ, UnsupportedSchedZfhmin; // Bypasses (none) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR7.td b/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR7.td index 4631474a945cb..decd578360753 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR7.td @@ -241,6 +241,7 @@ multiclass SCR7_Other { // Unsupported scheduling classes for SCR7. multiclass SCR7_Unsupported { + defm : UnsupportedSchedQ; defm : UnsupportedSchedSFB; defm : UnsupportedSchedV; defm : UnsupportedSchedXsfvcp; diff --git a/llvm/lib/Target/RISCV/RISCVSchedTTAscalonD8.td b/llvm/lib/Target/RISCV/RISCVSchedTTAscalonD8.td index 2afe02552974e..5322de100d0ad 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedTTAscalonD8.td +++ b/llvm/lib/Target/RISCV/RISCVSchedTTAscalonD8.td @@ -318,6 +318,7 @@ def : ReadAdvance<ReadSingleBitImm, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedXsfvcp; defm : UnsupportedSchedZabha; diff --git a/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td b/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td index 16d192feafd29..3076a2ebb813d 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td +++ b/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td @@ -306,6 +306,7 @@ def : ReadAdvance<ReadXPERM, 0>; //===----------------------------------------------------------------------===// // Unsupported extensions +defm : UnsupportedSchedQ; defm : UnsupportedSchedV; defm : UnsupportedSchedZfa; defm : UnsupportedSchedZfhmin; diff --git a/llvm/lib/Target/RISCV/RISCVSchedule.td b/llvm/lib/Target/RISCV/RISCVSchedule.td index ceaeb85d421ff..c8b0f0c9325f7 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedule.td +++ b/llvm/lib/Target/RISCV/RISCVSchedule.td @@ -43,34 +43,43 @@ def WriteAtomicSTD : SchedWrite; // Atomic store double word def WriteFAdd16 : SchedWrite; // 16-bit floating point addition/subtraction def WriteFAdd32 : SchedWrite; // 32-bit floating point addition/subtraction def WriteFAdd64 : SchedWrite; // 64-bit floating point addition/subtraction +def WriteFAdd128 : SchedWrite; // 128-bit floating point addition/subtraction def WriteFMul16 : SchedWrite; // 16-bit floating point multiply def WriteFMul32 : SchedWrite; // 32-bit floating point multiply def WriteFMul64 : SchedWrite; // 64-bit floating point multiply +def WriteFMul128 : SchedWrite; // 128-bit floating point multiply def WriteFMA16 : SchedWrite; // 16-bit floating point fused multiply-add def WriteFMA32 : SchedWrite; // 32-bit floating point fused multiply-add def WriteFMA64 : SchedWrite; // 64-bit floating point fused multiply-add +def WriteFMA128 : SchedWrite; // 128-bit floating point fused multiply-add def WriteFDiv16 : SchedWrite; // 16-bit floating point divide def WriteFDiv32 : SchedWrite; // 32-bit floating point divide def WriteFDiv64 : SchedWrite; // 64-bit floating point divide +def WriteFDiv128 : SchedWrite; // 128-bit floating point divide def WriteFSqrt16 : SchedWrite; // 16-bit floating point sqrt def WriteFSqrt32 : SchedWrite; // 32-bit floating point sqrt def WriteFSqrt64 : SchedWrite; // 64-bit floating point sqrt +def WriteFSqrt128 : SchedWrite; // 128-bit floating point sqrt // Integer to float conversions def WriteFCvtI32ToF16 : SchedWrite; def WriteFCvtI32ToF32 : SchedWrite; def WriteFCvtI32ToF64 : SchedWrite; +def WriteFCvtI32ToF128 : SchedWrite; def WriteFCvtI64ToF16 : SchedWrite; // RV64I only def WriteFCvtI64ToF32 : SchedWrite; // RV64I only def WriteFCvtI64ToF64 : SchedWrite; // RV64I only +def WriteFCvtI64ToF128 : SchedWrite; // RV64I only -//Float to integer conversions +// Float to integer conversions def WriteFCvtF16ToI32 : SchedWrite; def WriteFCvtF16ToI64 : SchedWrite; // RV64I only def WriteFCvtF32ToI32 : SchedWrite; def WriteFCvtF32ToI64 : SchedWrite; // RV64I only def WriteFCvtF64ToI32 : SchedWrite; def WriteFCvtF64ToI64 : SchedWrite; // RV64I only +def WriteFCvtF128ToI32 : SchedWrite; +def WriteFCvtF128ToI64 : SchedWrite; // RV64I only // Float to float conversions def WriteFCvtF32ToF64 : SchedWrite; @@ -79,8 +88,12 @@ def WriteFCvtF16ToF32 : SchedWrite; def WriteFCvtF32ToF16 : SchedWrite; def WriteFCvtF16ToF64 : SchedWrite; def WriteFCvtF64ToF16 : SchedWrite; +def WriteFCvtF128ToF32 : SchedWrite; +def WriteFCvtF128ToF64 : SchedWrite; +def WriteFCvtF32ToF128 : SchedWrite; +def WriteFCvtF64ToF128 : SchedWrite; -// Zfa found instructions. +// Zfa fround instructions. def WriteFRoundF32 : SchedWrite; def WriteFRoundF64 : SchedWrite; def WriteFRoundF16 : SchedWrite; @@ -88,15 +101,19 @@ def WriteFRoundF16 : SchedWrite; def WriteFClass16 : SchedWrite; // 16-bit floating point classify def WriteFClass32 : SchedWrite; // 32-bit floating point classify def WriteFClass64 : SchedWrite; // 64-bit floating point classify +def WriteFClass128 : SchedWrite; // 128-bit floating point classify def WriteFCmp16 : SchedWrite; // 16-bit floating point compare def WriteFCmp32 : SchedWrite; // 32-bit floating point compare def WriteFCmp64 : SchedWrite; // 64-bit floating point compare +def WriteFCmp128 : SchedWrite; // 128-bit floating point compare def WriteFSGNJ16 : SchedWrite; // 16-bit floating point sign-injection def WriteFSGNJ32 : SchedWrite; // 32-bit floating point sign-injection def WriteFSGNJ64 : SchedWrite; // 64-bit floating point sign-injection +def WriteFSGNJ128 : SchedWrite; // 128-bit floating point sign-injection def WriteFMinMax16 : SchedWrite; // 16-bit floating point min or max def WriteFMinMax32 : SchedWrite; // 32-bit floating point min or max def WriteFMinMax64 : SchedWrite; // 64-bit floating point min or max +def WriteFMinMax128 : SchedWrite; // 128-bit floating point min or max def WriteFMovF16ToI16 : SchedWrite; def WriteFMovI16ToF16 : SchedWrite; @@ -112,9 +129,11 @@ def WriteFLI64 : SchedWrite; // Floating point constant load def WriteFLD16 : SchedWrite; // Floating point sp load def WriteFLD32 : SchedWrite; // Floating point sp load def WriteFLD64 : SchedWrite; // Floating point dp load +def WriteFLD128 : SchedWrite; // Floating point qp load def WriteFST16 : SchedWrite; // Floating point sp store def WriteFST32 : SchedWrite; // Floating point sp store def WriteFST64 : SchedWrite; // Floating point dp store +def WriteFST128 : SchedWrite; // Floating point qp store // short forward branch for Bullet def WriteSFB : SchedWrite; @@ -156,42 +175,55 @@ def ReadAtomicSTD : SchedRead; // Atomic store double word def ReadFAdd16 : SchedRead; // 16-bit floating point addition/subtraction def ReadFAdd32 : SchedRead; // 32-bit floating point addition/subtraction def ReadFAdd64 : SchedRead; // 64-bit floating point addition/subtraction +def ReadFAdd128 : SchedRead; // 128-bit floating point addition/subtraction def ReadFMul16 : SchedRead; // 16-bit floating point multiply def ReadFMul32 : SchedRead; // 32-bit floating point multiply def ReadFMul64 : SchedRead; // 64-bit floating point multiply +def ReadFMul128 : SchedRead; // 128-bit floating point multiply def ReadFMA16 : SchedRead; // 16-bit floating point fused multiply-add def ReadFMA16Addend : SchedRead; // 16-bit floating point fused multiply-add (addend) def ReadFMA32 : SchedRead; // 32-bit floating point fused multiply-add def ReadFMA32Addend : SchedRead; // 32-bit floating point fused multiply-add (addend) def ReadFMA64 : SchedRead; // 64-bit floating point fused multiply-add def ReadFMA64Addend : SchedRead; // 64-bit floating point fused multiply-add (addend) +def ReadFMA128 : SchedRead; // 128-bit floating point fused multiply-add +def ReadFMA128Addend: SchedRead; // 128-bit floating point fused multiply-add (addend) def ReadFDiv16 : SchedRead; // 16-bit floating point divide def ReadFDiv32 : SchedRead; // 32-bit floating point divide def ReadFDiv64 : SchedRead; // 64-bit floating point divide +def ReadFDiv128 : SchedRead; // 128-bit floating point divide def ReadFSqrt16 : SchedRead; // 16-bit floating point sqrt def ReadFSqrt32 : SchedRead; // 32-bit floating point sqrt def ReadFSqrt64 : SchedRead; // 64-bit floating point sqrt +def ReadFSqrt128 : SchedRead; // 128-bit floating point sqrt def ReadFCmp16 : SchedRead; def ReadFCmp32 : SchedRead; def ReadFCmp64 : SchedRead; +def ReadFCmp128 : SchedRead; def ReadFSGNJ16 : SchedRead; def ReadFSGNJ32 : SchedRead; def ReadFSGNJ64 : SchedRead; +def ReadFSGNJ128 : SchedRead; def ReadFMinMax16 : SchedRead; def ReadFMinMax32 : SchedRead; def ReadFMinMax64 : SchedRead; +def ReadFMinMax128 : SchedRead; def ReadFCvtF16ToI32 : SchedRead; def ReadFCvtF16ToI64 : SchedRead; def ReadFCvtF32ToI32 : SchedRead; def ReadFCvtF32ToI64 : SchedRead; def ReadFCvtF64ToI32 : SchedRead; def ReadFCvtF64ToI64 : SchedRead; +def ReadFCvtF128ToI32 : SchedRead; +def ReadFCvtF128ToI64 : SchedRead; def ReadFCvtI32ToF16 : SchedRead; def ReadFCvtI32ToF32 : SchedRead; def ReadFCvtI32ToF64 : SchedRead; +def ReadFCvtI32ToF128 : SchedRead; def ReadFCvtI64ToF16 : SchedRead; def ReadFCvtI64ToF32 : SchedRead; def ReadFCvtI64ToF64 : SchedRead; +def ReadFCvtI64ToF128 : SchedRead; def ReadFMovF16ToI16 : SchedRead; def ReadFMovI16ToF16 : SchedRead; def ReadFMovF32ToI32 : SchedRead; @@ -204,12 +236,19 @@ def ReadFCvtF16ToF32 : SchedRead; def ReadFCvtF32ToF16 : SchedRead; def ReadFCvtF16ToF64 : SchedRead; def ReadFCvtF64ToF16 : SchedRead; +def ReadFCvtF128ToF32 : SchedRead; +def ReadFCvtF128ToF64 : SchedRead; +def ReadFCvtF32ToF128 : SchedRead; +def ReadFCvtF64ToF128 : SchedRead; + def ReadFRoundF16 : SchedRead; def ReadFRoundF32 : SchedRead; def ReadFRoundF64 : SchedRead; + def ReadFClass16 : SchedRead; def ReadFClass32 : SchedRead; def ReadFClass64 : SchedRead; +def ReadFClass128 : SchedRead; // For CPUs that support Zfhmin, but not Zfh. multiclass UnsupportedSchedZfh { @@ -266,7 +305,50 @@ def : ReadAdvance<ReadFMovF16ToI16, 0>; } // Unsupported = true } -multiclass UnsupportedSchedD { +multiclass UnsupportedSchedQ { +let Unsupported = true in { +def : WriteRes<WriteFST128, []>; +def : WriteRes<WriteFLD128, []>; +def : WriteRes<WriteFAdd128, []>; +def : WriteRes<WriteFSGNJ128, []>; +def : WriteRes<WriteFMinMax128, []>; +def : WriteRes<WriteFCvtI32ToF128, []>; +def : WriteRes<WriteFCvtI64ToF128, []>; +def : WriteRes<WriteFCvtF128ToI32, []>; +def : WriteRes<WriteFCvtF128ToI64, []>; +def : WriteRes<WriteFCvtF32ToF128, []>; +def : WriteRes<WriteFCvtF128ToF32, []>; +def : WriteRes<WriteFCvtF64ToF128, []>; +def : WriteRes<WriteFCvtF128ToF64, []>; +def : WriteRes<WriteFClass128, []>; +def : WriteRes<WriteFCmp128, []>; +def : WriteRes<WriteFMul128, []>; +def : WriteRes<WriteFMA128, []>; +def : WriteRes<WriteFDiv128, []>; +def : WriteRes<WriteFSqrt128, []>; + +def : ReadAdvance<ReadFAdd128, 0>; +def : ReadAdvance<ReadFMul128, 0>; +def : ReadAdvance<ReadFMA128, 0>; +def : ReadAdvance<ReadFMA128Addend, 0>; +def : ReadAdvance<ReadFDiv128, 0>; +def : ReadAdvance<ReadFSqrt128, 0>; +def : ReadAdvance<ReadFCmp128, 0>; +def : ReadAdvance<ReadFSGNJ128, 0>; +def : ReadAdvance<ReadFMinMax128, 0>; +def : ReadAdvance<ReadFCvtF128ToI32, 0>; +def : ReadAdvance<ReadFCvtF128ToI64, 0>; +def : ReadAdvance<ReadFCvtI32ToF128, 0>; +def : ReadAdvance<ReadFCvtI64ToF128, 0>; +def : ReadAdvance<ReadFCvtF32ToF128, 0>; +def : ReadAdvance<ReadFCvtF128ToF32, 0>; +def : ReadAdvance<ReadFCvtF64ToF128, 0>; +def : ReadAdvance<ReadFCvtF128ToF64, 0>; +def : ReadAdvance<ReadFClass128, 0>; +} // Unsupported = true +} + +multiclass UnsupportedSchedD : UnsupportedSchedQ { let Unsupported = true in { def : WriteRes<WriteFST64, []>; def : WriteRes<WriteFLD64, []>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 035ce4745cfd9..72bfa55c7debc 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -198,6 +198,9 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { bool useLoadStorePairs() const; bool useCCMovInsn() const; unsigned getFLen() const { + if (HasStdExtQ) + return 128; + if (HasStdExtD) return 64; diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index ad7bdcd112459..e76ddd4b648dc 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -925,8 +925,9 @@ void RISCVISAInfo::updateImpliedLengths() { assert(FLen == 0 && MaxELenFp == 0 && MaxELen == 0 && MinVLen == 0 && "Expected lengths to be initialied to zero"); - // TODO: Handle q extension. - if (Exts.count("d")) + if (Exts.count("q")) + FLen = 128; + else if (Exts.count("d")) FLen = 64; else if (Exts.count("f")) FLen = 32; diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index 49e05f9acb4b2..4ab0aeccaa57d 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -9,6 +9,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+zba,+zbb,+zbs %s -o - | FileCheck --check-prefixes=CHECK,RV32COMBINEINTOB %s ; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefixes=CHECK,RV32F %s ; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefixes=CHECK,RV32D %s +; RUN: llc -mtriple=riscv32 -mattr=+q %s -o - | FileCheck --check-prefixes=CHECK,RV32Q %s ; RUN: llc -mtriple=riscv32 -mattr=+c %s -o - | FileCheck --check-prefixes=CHECK,RV32C %s ; RUN: llc -mtriple=riscv32 -mattr=+c,+f %s -o - | FileCheck --check-prefixes=CHECK,RV32CF %s ; RUN: llc -mtriple=riscv32 -mattr=+c,+d %s -o - | FileCheck --check-prefixes=CHECK,RV32CD %s @@ -180,6 +181,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+zba,+zbb,+zbs %s -o - | FileCheck --check-prefixes=CHECK,RV64COMBINEINTOB %s ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefixes=CHECK,RV64F %s ; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefixes=CHECK,RV64D %s +; RUN: llc -mtriple=riscv64 -mattr=+q %s -o - | FileCheck --check-prefixes=CHECK,RV64Q %s ; RUN: llc -mtriple=riscv64 -mattr=+c %s -o - | FileCheck --check-prefixes=CHECK,RV64C %s ; RUN: llc -mtriple=riscv64 -mattr=+c,+f %s -o - | FileCheck --check-prefixes=CHECK,RV64CF %s ; RUN: llc -mtriple=riscv64 -mattr=+c,+d %s -o - | FileCheck --check-prefixes=CHECK,RV64CD %s @@ -352,6 +354,7 @@ ; RV32COMBINEINTOB: .attribute 5, "rv32i2p1_b1p0_zba1p0_zbb1p0_zbs1p0" ; RV32F: .attribute 5, "rv32i2p1_f2p2_zicsr2p0" ; RV32D: .attribute 5, "rv32i2p1_f2p2_d2p2_zicsr2p0" +; RV32Q: .attribute 5, "rv32i2p1_f2p2_d2p2_q2p2_zicsr2p0" ; RV32C: .attribute 5, "rv32i2p1_c2p0_zca1p0" ; RV32CF: .attribute 5, "rv32i2p1_f2p2_c2p0_zicsr2p0_zca1p0_zcf1p0" ; RV32CD: .attribute 5, "rv32i2p1_f2p2_d2p2_c2p0_zicsr2p0_zca1p0_zcd1p0_zcf1p0" @@ -520,6 +523,7 @@ ; RV64COMBINEINTOB: .attribute 5, "rv64i2p1_b1p0_zba1p0_zbb1p0_zbs1p0" ; RV64F: .attribute 5, "rv64i2p1_f2p2_zicsr2p0" ; RV64D: .attribute 5, "rv64i2p1_f2p2_d2p2_zicsr2p0" +; RV64Q: .attribute 5, "rv64i2p1_f2p2_d2p2_q2p2_zicsr2p0" ; RV64C: .attribute 5, "rv64i2p1_c2p0_zca1p0" ; RV64CF: .attribute 5, "rv64i2p1_f2p2_c2p0_zicsr2p0_zca1p0" ; RV64CD: .attribute 5, "rv64i2p1_f2p2_d2p2_c2p0_zicsr2p0_zca1p0_zcd1p0" diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll index 5f322dc04fedb..2e66a81571672 100644 --- a/llvm/test/CodeGen/RISCV/features-info.ll +++ b/llvm/test/CodeGen/RISCV/features-info.ll @@ -74,6 +74,7 @@ ; CHECK-NEXT: predictable-select-expensive - Prefer likely predicted branches over selects. ; CHECK-NEXT: prefer-vsetvli-over-read-vlenb - Prefer vsetvli over read vlenb CSR to calculate VLEN. ; CHECK-NEXT: prefer-w-inst - Prefer instructions with W suffix. +; CHECK-NEXT: q - 'Q' (Quad-Precision Floating-Point). ; CHECK-NEXT: relax - Enable Linker relaxation.. ; CHECK-NEXT: reserve-x1 - Reserve X1. ; CHECK-NEXT: reserve-x10 - Reserve X10. diff --git a/llvm/test/MC/RISCV/rv32q-invalid.s b/llvm/test/MC/RISCV/rv32q-invalid.s new file mode 100644 index 0000000000000..9b74f9f1d59c1 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32q-invalid.s @@ -0,0 +1,21 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+q < %s 2>&1 | FileCheck %s + +# Out of range immediates +## simm12 +flq ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an integer in the range [-2048, 2047] +fsq ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an integer in the range [-2048, 2047] + +# Memory operand not formatted correctly +flq ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +fsq ft2, a1, 100 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + +# Invalid register names +flq ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction +flq ft1, 100(a10) # CHECK: :[[@LINE]]:14: error: expected register +fsgnjn.q fa100, fa2, fa3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + +# Integer registers where FP regs are expected +fadd.q a2, a1, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction + +# FP registers where integer regs are expected +fcvt.wu.q ft2, a1 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction diff --git a/llvm/test/MC/RISCV/rv64q-invalid.s b/llvm/test/MC/RISCV/rv64q-invalid.s new file mode 100644 index 0000000000000..ac469c268d7ad --- /dev/null +++ b/llvm/test/MC/RISCV/rv64q-invalid.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc -triple riscv64 -mattr=+q < %s 2>&1 | FileCheck %s + +# Integer registers where FP regs are expected +fcvt.l.q ft0, a0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction +fcvt.lu.q ft1, a1 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction + +# FP registers where integer regs are expected +fcvt.q.l a3, ft3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction +fcvt.q.lu a4, ft4 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction diff --git a/llvm/test/MC/RISCV/rv64q-valid.s b/llvm/test/MC/RISCV/rv64q-valid.s new file mode 100644 index 0000000000000..81bb2852eac0f --- /dev/null +++ b/llvm/test/MC/RISCV/rv64q-valid.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+q -M no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+q < %s \ +# RUN: | llvm-objdump --mattr=+q -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 -mattr=+q < %s 2>&1 \ +# RUN: | FileCheck -check-prefix=CHECK-RV32 %s + +# CHECK-ASM-AND-OBJ: fcvt.l.q a0, ft0, dyn +# CHECK-ASM: encoding: [0x53,0x75,0x20,0xc6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.l.q a0, ft0, dyn +# CHECK-ASM-AND-OBJ: fcvt.lu.q a1, ft1, dyn +# CHECK-ASM: encoding: [0xd3,0xf5,0x30,0xc6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.lu.q a1, ft1, dyn +# CHECK-ASM-AND-OBJ: fcvt.q.l ft3, a3, dyn +# CHECK-ASM: encoding: [0xd3,0xf1,0x26,0xd6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.q.l ft3, a3, dyn +# CHECK-ASM-AND-OBJ: fcvt.q.lu ft4, a4, dyn +# CHECK-ASM: encoding: [0x53,0x72,0x37,0xd6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.q.lu ft4, a4, dyn + +# Rounding modes +# CHECK-ASM-AND-OBJ: fcvt.q.l ft3, a3 +# CHECK-ASM: encoding: [0xd3,0x81,0x26,0xd6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.q.l ft3, a3, rne +# CHECK-ASM-AND-OBJ: fcvt.q.lu ft4, a4, rtz +# CHECK-ASM: encoding: [0x53,0x12,0x37,0xd6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.q.lu ft4, a4, rtz +# CHECK-ASM-AND-OBJ: fcvt.l.q a0, ft0, rdn +# CHECK-ASM: encoding: [0x53,0x25,0x20,0xc6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.l.q a0, ft0, rdn +# CHECK-ASM-AND-OBJ: fcvt.lu.q a1, ft1, rup +# CHECK-ASM: encoding: [0xd3,0xb5,0x30,0xc6] +# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} +fcvt.lu.q a1, ft1, rup diff --git a/llvm/test/MC/RISCV/rvq-aliases-valid.s b/llvm/test/MC/RISCV/rvq-aliases-valid.s new file mode 100644 index 0000000000000..85e24f0e970cb --- /dev/null +++ b/llvm/test/MC/RISCV/rvq-aliases-valid.s @@ -0,0 +1,55 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+q -M no-aliases \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv32 -mattr=+q \ +# RUN: | FileCheck -check-prefix=CHECK-ALIAS %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+q -M no-aliases \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+q \ +# RUN: | FileCheck -check-prefix=CHECK-ALIAS %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+q < %s \ +# RUN: | llvm-objdump -d --mattr=+q --no-print-imm-hex -M no-aliases - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+q < %s \ +# RUN: | llvm-objdump -d --mattr=+q --no-print-imm-hex - \ +# RUN: | FileCheck -check-prefix=CHECK-ALIAS %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+q < %s \ +# RUN: | llvm-objdump -d --mattr=+q --no-print-imm-hex -M no-aliases - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+q < %s \ +# RUN: | llvm-objdump -d --mattr=+q --no-print-imm-hex - \ +# RUN: | FileCheck -check-prefix=CHECK-ALIAS %s + +##===----------------------------------------------------------------------===## +## Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) +##===----------------------------------------------------------------------===## + +# CHECK-INST: flq ft0, 0(a0) +# CHECK-ALIAS: flq ft0, 0(a0) +flq f0, (a0) +# CHECK-INST: fsq ft0, 0(a0) +# CHECK-ALIAS: fsq ft0, 0(a0) +fsq f0, (a0) + +# CHECK-INST: fsgnj.q ft0, ft1, ft1 +# CHECK-ALIAS: fmv.q ft0, ft1 +fmv.q f0, f1 +# CHECK-INST: fsgnjx.q ft1, ft2, ft2 +# CHECK-ALIAS: fabs.q ft1, ft2 +fabs.q f1, f2 +# CHECK-INST: fsgnjn.q ft2, ft3, ft3 +# CHECK-ALIAS: fneg.q ft2, ft3 +fneg.q f2, f3 + +# CHECK-INST: flt.q tp, ft6, ft5 +# CHECK-ALIAS: flt.q tp, ft6, ft5 +fgt.q x4, f5, f6 +# CHECK-INST: fle.q t2, fs1, fs0 +# CHECK-ALIAS: fle.q t2, fs1, fs0 +fge.q x7, f8, f9 + +# CHECK-INST: flq ft0, 0(a0) +# CHECK-ALIAS: flq ft0, 0(a0) +flq f0, (x10) +# CHECK-INST: fsq ft0, 0(a0) +# CHECK-ALIAS: fsq ft0, 0(a0) +fsq f0, (x10) diff --git a/llvm/test/MC/RISCV/rvq-pseudos.s b/llvm/test/MC/RISCV/rvq-pseudos.s new file mode 100644 index 0000000000000..9c49a1bac3f15 --- /dev/null +++ b/llvm/test/MC/RISCV/rvq-pseudos.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+q | FileCheck %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+q | FileCheck %s + +# CHECK: .Lpcrel_hi0: +# CHECK: auipc a2, %pcrel_hi(a_symbol) +# CHECK: flq fa2, %pcrel_lo(.Lpcrel_hi0)(a2) +flq fa2, a_symbol, a2 + +# CHECK: .Lpcrel_hi1: +# CHECK: auipc a3, %pcrel_hi(a_symbol) +# CHECK: fsq fa2, %pcrel_lo(.Lpcrel_hi1)(a3) +fsq fa2, a_symbol, a3 diff --git a/llvm/test/MC/RISCV/rvq-valid.s b/llvm/test/MC/RISCV/rvq-valid.s new file mode 100644 index 0000000000000..fe224f85cd699 --- /dev/null +++ b/llvm/test/MC/RISCV/rvq-valid.s @@ -0,0 +1,184 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+q -M no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+q < %s \ +# RUN: | llvm-objdump --no-print-imm-hex --mattr=+q -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+q -M no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+q < %s \ +# RUN: | llvm-objdump --no-print-imm-hex --mattr=+q -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# Support for the 'Q' extension implies support for 'D' and 'F' + +# CHECK-ASM-AND-OBJ: fadd.d fs10, fs11, ft8, dyn +# CHECK-ASM: encoding: [0x53,0xfd,0xcd,0x03] +fadd.d f26, f27, f28, dyn + +# CHECK-ASM-AND-OBJ: fadd.s fs10, fs11, ft8 +# CHECK-ASM: encoding: [0x53,0xfd,0xcd,0x01] +fadd.s f26, f27, f28 + +# CHECK-ASM-AND-OBJ: flq ft0, 12(a0) +# CHECK-ASM: encoding: [0x07,0x40,0xc5,0x00] +flq f0, 12(a0) +# CHECK-ASM-AND-OBJ: flq ft1, 4(ra) +# CHECK-ASM: encoding: [0x87,0xc0,0x40,0x00] +flq f1, +4(ra) +# CHECK-ASM-AND-OBJ: flq ft2, -2048(a3) +# CHECK-ASM: encoding: [0x07,0xc1,0x06,0x80] +flq f2, -2048(x13) +# CHECK-ASM: flq ft3, %lo(2048)(s1) # encoding: [0x87,0xc1,0bAAAA0100,A] +# CHECK-OBJ: flq ft3, -2048(s1) +flq f3, %lo(2048)(s1) +# CHECK-ASM-AND-OBJ: flq ft4, 2047(s2) +# CHECK-ASM: encoding: [0x07,0x42,0xf9,0x7f] +flq f4, 2047(s2) +# CHECK-ASM-AND-OBJ: flq ft5, 0(s3) +# CHECK-ASM: encoding: [0x87,0xc2,0x09,0x00] +flq f5, 0(s3) + +# CHECK-ASM-AND-OBJ: fsq ft6, 2047(s4) +# CHECK-ASM: encoding: [0xa7,0x4f,0x6a,0x7e] +fsq f6, 2047(s4) +# CHECK-ASM-AND-OBJ: fsq ft7, -2048(s5) +# CHECK-ASM: encoding: [0x27,0xc0,0x7a,0x80] +fsq f7, -2048(s5) +# CHECK-ASM: fsq fs0, %lo(2048)(s6) # encoding: [0x27'A',0x40'A',0x8b'A',A] +# CHECK-OBJ: fsq fs0, -2048(s6) +fsq f8, %lo(2048)(s6) +# CHECK-ASM-AND-OBJ: fsq fs1, 999(s7) +# CHECK-ASM: encoding: [0xa7,0xc3,0x9b,0x3e] +fsq f9, 999(s7) + +# CHECK-ASM-AND-OBJ: fmadd.q fa0, fa1, fa2, fa3, dyn +# CHECK-ASM: encoding: [0x43,0xf5,0xc5,0x6e] +fmadd.q f10, f11, f12, f13, dyn +# CHECK-ASM-AND-OBJ: fmsub.q fa4, fa5, fa6, fa7, dyn +# CHECK-ASM: encoding: [0x47,0xf7,0x07,0x8f] +fmsub.q f14, f15, f16, f17, dyn +# CHECK-ASM-AND-OBJ: fnmsub.q fs2, fs3, fs4, fs5, dyn +# CHECK-ASM: encoding: [0x4b,0xf9,0x49,0xaf] +fnmsub.q f18, f19, f20, f21, dyn +# CHECK-ASM-AND-OBJ: fnmadd.q fs6, fs7, fs8, fs9, dyn +# CHECK-ASM: encoding: [0x4f,0xfb,0x8b,0xcf] +fnmadd.q f22, f23, f24, f25, dyn + +# CHECK-ASM-AND-OBJ: fadd.q fs10, fs11, ft8, dyn +# CHECK-ASM: encoding: [0x53,0xfd,0xcd,0x07] +fadd.q f26, f27, f28, dyn +# CHECK-ASM-AND-OBJ: fsub.q ft9, ft10, ft11, dyn +# CHECK-ASM: encoding: [0xd3,0x7e,0xff,0x0f] +fsub.q f29, f30, f31, dyn +# CHECK-ASM-AND-OBJ: fmul.q ft0, ft1, ft2, dyn +# CHECK-ASM: encoding: [0x53,0xf0,0x20,0x16] +fmul.q ft0, ft1, ft2, dyn +# CHECK-ASM-AND-OBJ: fdiv.q ft3, ft4, ft5, dyn +# CHECK-ASM: encoding: [0xd3,0x71,0x52,0x1e] +fdiv.q ft3, ft4, ft5, dyn +# CHECK-ASM-AND-OBJ: fsqrt.q ft6, ft7, dyn +# CHECK-ASM: encoding: [0x53,0xf3,0x03,0x5e] +fsqrt.q ft6, ft7, dyn +# CHECK-ASM-AND-OBJ: fsgnj.q fs1, fa0, fa1 +# CHECK-ASM: encoding: [0xd3,0x04,0xb5,0x26] +fsgnj.q fs1, fa0, fa1 +# CHECK-ASM-AND-OBJ: fsgnjn.q fa1, fa3, fa4 +# CHECK-ASM: encoding: [0xd3,0x95,0xe6,0x26] +fsgnjn.q fa1, fa3, fa4 +# CHECK-ASM-AND-OBJ: fsgnjx.q fa3, fa2, fa1 +# CHECK-ASM: encoding: [0xd3,0x26,0xb6,0x26] +fsgnjx.q fa3, fa2, fa1 +# CHECK-ASM-AND-OBJ: fmin.q fa5, fa6, fa7 +# CHECK-ASM: encoding: [0xd3,0x07,0x18,0x2f] +fmin.q fa5, fa6, fa7 +# CHECK-ASM-AND-OBJ: fmax.q fs2, fs3, fs4 +# CHECK-ASM: encoding: [0x53,0x99,0x49,0x2f] +fmax.q fs2, fs3, fs4 + +# CHECK-ASM-AND-OBJ: fcvt.s.q fs5, fs6, dyn +# CHECK-ASM: encoding: [0xd3,0x7a,0x3b,0x40] +fcvt.s.q fs5, fs6, dyn +# CHECK-ASM-AND-OBJ: fcvt.q.s fs7, fs8 +# CHECK-ASM: encoding: [0xd3,0x0b,0x0c,0x46] +fcvt.q.s fs7, fs8 +# CHECK-ASM-AND-OBJ: fcvt.q.s fs7, fs8, rup +# CHECK-ASM: encoding: [0xd3,0x3b,0x0c,0x46] +fcvt.q.s fs7, fs8, rup +# CHECK-ASM-AND-OBJ: fcvt.d.q fs5, fs6, dyn +# CHECK-ASM: encoding: [0xd3,0x7a,0x3b,0x42] +fcvt.d.q fs5, fs6, dyn +# CHECK-ASM-AND-OBJ: fcvt.q.d fs7, fs8 +# CHECK-ASM: encoding: [0xd3,0x0b,0x1c,0x46] +fcvt.q.d fs7, fs8 +# CHECK-ASM-AND-OBJ: fcvt.q.d fs7, fs8, rup +# CHECK-ASM: encoding: [0xd3,0x3b,0x1c,0x46] +fcvt.q.d fs7, fs8, rup +# CHECK-ASM-AND-OBJ: feq.q a1, fs8, fs9 +# CHECK-ASM: encoding: [0xd3,0x25,0x9c,0xa7] +feq.q a1, fs8, fs9 +# CHECK-ASM-AND-OBJ: flt.q a2, fs10, fs11 +# CHECK-ASM: encoding: [0x53,0x16,0xbd,0xa7] +flt.q a2, fs10, fs11 +# CHECK-ASM-AND-OBJ: fle.q a3, ft8, ft9 +# CHECK-ASM: encoding: [0xd3,0x06,0xde,0xa7] +fle.q a3, ft8, ft9 +# CHECK-ASM-AND-OBJ: fclass.q a3, ft10 +# CHECK-ASM: encoding: [0xd3,0x16,0x0f,0xe6] +fclass.q a3, ft10 + +# CHECK-ASM-AND-OBJ: fcvt.w.q a4, ft11, dyn +# CHECK-ASM: encoding: [0x53,0xf7,0x0f,0xc6] +fcvt.w.q a4, ft11, dyn +# CHECK-ASM-AND-OBJ: fcvt.q.w ft0, a5 +# CHECK-ASM: encoding: [0x53,0x80,0x07,0xd6] +fcvt.q.w ft0, a5 +# CHECK-ASM-AND-OBJ: fcvt.q.w ft0, a5, rup +# CHECK-ASM: encoding: [0x53,0xb0,0x07,0xd6] +fcvt.q.w ft0, a5, rup +# CHECK-ASM-AND-OBJ: fcvt.q.wu ft1, a6 +# CHECK-ASM: encoding: [0xd3,0x00,0x18,0xd6] +fcvt.q.wu ft1, a6 +# CHECK-ASM-AND-OBJ: fcvt.q.wu ft1, a6, rup +# CHECK-ASM: encoding: [0xd3,0x30,0x18,0xd6] +fcvt.q.wu ft1, a6, rup + +# Rounding modes + +# CHECK-ASM-AND-OBJ: fmadd.q fa0, fa1, fa2, fa3, rne +# CHECK-ASM: encoding: [0x43,0x85,0xc5,0x6e] +fmadd.q f10, f11, f12, f13, rne +# CHECK-ASM-AND-OBJ: fmsub.q fa4, fa5, fa6, fa7, rtz +# CHECK-ASM: encoding: [0x47,0x97,0x07,0x8f] +fmsub.q f14, f15, f16, f17, rtz +# CHECK-ASM-AND-OBJ: fnmsub.q fs2, fs3, fs4, fs5, rdn +# CHECK-ASM: encoding: [0x4b,0xa9,0x49,0xaf] +fnmsub.q f18, f19, f20, f21, rdn +# CHECK-ASM-AND-OBJ: fnmadd.q fs6, fs7, fs8, fs9, rup +# CHECK-ASM: encoding: [0x4f,0xbb,0x8b,0xcf] +fnmadd.q f22, f23, f24, f25, rup + +# CHECK-ASM-AND-OBJ: fadd.q fs10, fs11, ft8, rmm +# CHECK-ASM: encoding: [0x53,0xcd,0xcd,0x07] +fadd.q f26, f27, f28, rmm +# CHECK-ASM-AND-OBJ: fsub.q ft9, ft10, ft11 +# CHECK-ASM: encoding: [0xd3,0x7e,0xff,0x0f] +fsub.q f29, f30, f31, dyn +# CHECK-ASM-AND-OBJ: fmul.q ft0, ft1, ft2, rne +# CHECK-ASM: encoding: [0x53,0x80,0x20,0x16] +fmul.q ft0, ft1, ft2, rne +# CHECK-ASM-AND-OBJ: fdiv.q ft3, ft4, ft5, rtz +# CHECK-ASM: encoding: [0xd3,0x11,0x52,0x1e] +fdiv.q ft3, ft4, ft5, rtz + +# CHECK-ASM-AND-OBJ: fsqrt.q ft6, ft7, rdn +# CHECK-ASM: encoding: [0x53,0xa3,0x03,0x5e] +fsqrt.q ft6, ft7, rdn +# CHECK-ASM-AND-OBJ: fcvt.s.q fs5, fs6, rup +# CHECK-ASM: encoding: [0xd3,0x3a,0x3b,0x40] +fcvt.s.q fs5, fs6, rup +# CHECK-ASM-AND-OBJ: fcvt.w.q a4, ft11, rmm +# CHECK-ASM: encoding: [0x53,0xc7,0x0f,0xc6] +fcvt.w.q a4, ft11, rmm +# CHECK-ASM-AND-OBJ: fcvt.wu.q a5, ft10, dyn +# CHECK-ASM: encoding: [0xd3,0x77,0x1f,0xc6] +fcvt.wu.q a5, ft10, dyn diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index b8d33e81e6c90..8d32bb5ca1963 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -981,6 +981,7 @@ R"(All available -march extensions for RISC-V a 2.1 f 2.2 d 2.2 + q 2.2 c 2.0 b 1.0 v 1.0 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits