[clang] [llvm] [RISCV][MC] Add support for Q extension (PR #139369)
Iris Shi via llvm-commits
llvm-commits at lists.llvm.org
Sat May 10 07:31:36 PDT 2025
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/139369
>From 70a6d632c96de6564eea070d526bbbeaa8df3f08 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at 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 | 9 +
.../RISCV/Disassembler/RISCVDisassembler.cpp | 11 ++
llvm/lib/Target/RISCV/RISCVFeatures.td | 7 +
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 | 168 ++++++++++++++++
llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td | 20 +-
llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 18 ++
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 | 3 +-
.../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-valid.s | 184 ++++++++++++++++++
.../TargetParser/RISCVISAInfoTest.cpp | 1 +
35 files changed, 629 insertions(+), 32 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-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..442b3c32c779d 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) ||
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.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..7611125f88cf9
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoQ.td
@@ -0,0 +1,168 @@
+//===-- RISCVInstrInfoF.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>;
+}
+
+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_frm_m<0b1101011, 0b00000, Ext,
+ Ext.PrimaryTy, GPR, "fcvt.q.w">,
+ Sched<[WriteFCvtI32ToF128, ReadFCvtI32ToF128]>;
+
+ let mayRaiseFPException = 0 in
+ defm FCVT_Q_WU : FPUnaryOp_r_frm_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_frm_m<0b1101011, 0b00010, Ext, Ext.PrimaryTy,
+ GPR, "fcvt.q.l", [IsRV64]>,
+ Sched<[WriteFCvtI64ToF128, ReadFCvtI64ToF128]>;
+
+ let mayRaiseFPException = 0 in
+ defm FCVT_Q_LU : FPUnaryOp_r_frm_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>;
+ let usesCustomInserter = 1 in {
+ def PseudoQuietFLE_Q : PseudoQuietFCMP<FPR128>;
+ def PseudoQuietFLT_Q : PseudoQuietFCMP<FPR128>;
+ }
+} // Predicates = [HasStdExtQ]
\ No newline at end of file
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.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index eb3d5e553f1ef..4abed81c54216 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 : RISCVReg64<!cast<RISCVReg32>("F"#Index#"_F")>,
+ DwarfRegAlias<!cast<Register>("F"#Index#"_H")>;
+ }
}
// The order of registers represents the preferred allocation sequence,
@@ -462,6 +474,12 @@ 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..8e08d080205d9 100644
--- a/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td
+++ b/llvm/lib/Target/RISCV/RISCVSchedSyntacoreSCR345.td
@@ -197,8 +197,9 @@ multiclass SCR3_Unsupported :
SCR_Unsupported,
UnsupportedSchedF;
-multiclass SCR4_SCR5_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..31980d180af52
--- /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, rne
+# 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-valid.s b/llvm/test/MC/RISCV/rvq-valid.s
new file mode 100644
index 0000000000000..f6f2711b4478d
--- /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,0xf0,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,0x70,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
More information about the llvm-commits
mailing list