10b57cec5SDimitry Andric//===-- RISCVInstrInfoF.td - RISC-V 'F' instructions -------*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'F',
100b57cec5SDimitry Andric// Single-Precision Floating-Point instruction set extension.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// RISC-V specific DAG Nodes.
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricdef SDT_RISCVFMV_W_X_RV64
190b57cec5SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
200b57cec5SDimitry Andricdef SDT_RISCVFMV_X_ANYEXTW_RV64
210b57cec5SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;
220eae32dcSDimitry Andricdef SDT_RISCVFCVT_W_RV64
2304eeddc0SDimitry Andric    : SDTypeProfile<1, 2, [SDTCisVT<0, i64>, SDTCisFP<1>,
2404eeddc0SDimitry Andric                           SDTCisVT<2, i64>]>;
250eae32dcSDimitry Andricdef SDT_RISCVFCVT_X
2604eeddc0SDimitry Andric    : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>, SDTCisFP<1>,
2704eeddc0SDimitry Andric                           SDTCisVT<2, XLenVT>]>;
280b57cec5SDimitry Andric
29bdd1243dSDimitry Andricdef SDT_RISCVFROUND
30bdd1243dSDimitry Andric    : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
31bdd1243dSDimitry Andric                           SDTCisVT<3, XLenVT>]>;
325f757f3fSDimitry Andricdef SDT_RISCVFCLASS
3306c3fb27SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>;
3406c3fb27SDimitry Andric
355f757f3fSDimitry Andricdef riscv_fclass
365f757f3fSDimitry Andric    : SDNode<"RISCVISD::FCLASS", SDT_RISCVFCLASS>;
37bdd1243dSDimitry Andric
38bdd1243dSDimitry Andricdef riscv_fround
39bdd1243dSDimitry Andric    : SDNode<"RISCVISD::FROUND", SDT_RISCVFROUND>;
40bdd1243dSDimitry Andric
410b57cec5SDimitry Andricdef riscv_fmv_w_x_rv64
420b57cec5SDimitry Andric    : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>;
430b57cec5SDimitry Andricdef riscv_fmv_x_anyextw_rv64
440b57cec5SDimitry Andric    : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>;
4504eeddc0SDimitry Andricdef riscv_fcvt_w_rv64
4604eeddc0SDimitry Andric    : SDNode<"RISCVISD::FCVT_W_RV64", SDT_RISCVFCVT_W_RV64>;
4704eeddc0SDimitry Andricdef riscv_fcvt_wu_rv64
4804eeddc0SDimitry Andric    : SDNode<"RISCVISD::FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64>;
4904eeddc0SDimitry Andricdef riscv_fcvt_x
5004eeddc0SDimitry Andric    : SDNode<"RISCVISD::FCVT_X", SDT_RISCVFCVT_X>;
5104eeddc0SDimitry Andricdef riscv_fcvt_xu
5204eeddc0SDimitry Andric    : SDNode<"RISCVISD::FCVT_XU", SDT_RISCVFCVT_X>;
530eae32dcSDimitry Andric
5406c3fb27SDimitry Andricdef riscv_fmin : SDNode<"RISCVISD::FMIN", SDTFPBinOp>;
5506c3fb27SDimitry Andricdef riscv_fmax : SDNode<"RISCVISD::FMAX", SDTFPBinOp>;
5606c3fb27SDimitry Andric
5704eeddc0SDimitry Andricdef riscv_strict_fcvt_w_rv64
5804eeddc0SDimitry Andric    : SDNode<"RISCVISD::STRICT_FCVT_W_RV64", SDT_RISCVFCVT_W_RV64,
590eae32dcSDimitry Andric             [SDNPHasChain]>;
6004eeddc0SDimitry Andricdef riscv_strict_fcvt_wu_rv64
6104eeddc0SDimitry Andric    : SDNode<"RISCVISD::STRICT_FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64,
620eae32dcSDimitry Andric             [SDNPHasChain]>;
630eae32dcSDimitry Andric
6404eeddc0SDimitry Andricdef riscv_any_fcvt_w_rv64 : PatFrags<(ops node:$src, node:$frm),
6504eeddc0SDimitry Andric                                     [(riscv_strict_fcvt_w_rv64 node:$src, node:$frm),
6604eeddc0SDimitry Andric                                      (riscv_fcvt_w_rv64 node:$src, node:$frm)]>;
6704eeddc0SDimitry Andricdef riscv_any_fcvt_wu_rv64 : PatFrags<(ops node:$src, node:$frm),
6804eeddc0SDimitry Andric                                      [(riscv_strict_fcvt_wu_rv64 node:$src, node:$frm),
6904eeddc0SDimitry Andric                                       (riscv_fcvt_wu_rv64 node:$src, node:$frm)]>;
700b57cec5SDimitry Andric
7181ad6265SDimitry Andricdef any_fma_nsz : PatFrag<(ops node:$rs1, node:$rs2, node:$rs3),
7281ad6265SDimitry Andric                          (any_fma node:$rs1, node:$rs2, node:$rs3), [{
7381ad6265SDimitry Andric  return N->getFlags().hasNoSignedZeros();
7481ad6265SDimitry Andric}]>;
750b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
760b57cec5SDimitry Andric// Operand and SDNode transformation definitions.
770b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
780b57cec5SDimitry Andric
79d56accc7SDimitry Andric// Zfinx
80d56accc7SDimitry Andric
81d56accc7SDimitry Andricdef GPRAsFPR : AsmOperandClass {
82d56accc7SDimitry Andric  let Name = "GPRAsFPR";
83d56accc7SDimitry Andric  let ParserMethod = "parseGPRAsFPR";
84d56accc7SDimitry Andric  let RenderMethod = "addRegOperands";
85d56accc7SDimitry Andric}
86d56accc7SDimitry Andric
87d56accc7SDimitry Andricdef FPR32INX : RegisterOperand<GPRF32> {
88d56accc7SDimitry Andric  let ParserMatchClass = GPRAsFPR;
89d56accc7SDimitry Andric  let DecoderMethod = "DecodeGPRRegisterClass";
90d56accc7SDimitry Andric}
91d56accc7SDimitry Andric
9206c3fb27SDimitry Andric// Describes a combination of predicates from F/D/Zfh/Zfhmin or
9306c3fb27SDimitry Andric// Zfinx/Zdinx/Zhinx/Zhinxmin that are applied to scalar FP instruction.
9406c3fb27SDimitry Andric// Contains the DAGOperand for the primary type for the predicates. The primary
9506c3fb27SDimitry Andric// type may be unset for combinations of predicates like Zfh+D.
9606c3fb27SDimitry Andric// Also contains the DAGOperand for f16/f32/f64, instruction suffix, and
9706c3fb27SDimitry Andric// decoder namespace that go with an instruction given those predicates.
9806c3fb27SDimitry Andric//
9906c3fb27SDimitry Andric// The DAGOperand can be unset if the predicates are not enough to define it.
10006c3fb27SDimitry Andricclass ExtInfo<string suffix, string space, list<Predicate> predicates,
10106c3fb27SDimitry Andric              ValueType primaryvt, DAGOperand primaryty, DAGOperand f32ty,
10206c3fb27SDimitry Andric              DAGOperand f64ty, DAGOperand f16ty> {
10306c3fb27SDimitry Andric  list<Predicate> Predicates = predicates;
10406c3fb27SDimitry Andric  string Suffix = suffix;
10506c3fb27SDimitry Andric  string Space = space;
10606c3fb27SDimitry Andric  DAGOperand PrimaryTy = primaryty;
10706c3fb27SDimitry Andric  DAGOperand F16Ty = f16ty;
10806c3fb27SDimitry Andric  DAGOperand F32Ty = f32ty;
10906c3fb27SDimitry Andric  DAGOperand F64Ty = f64ty;
11006c3fb27SDimitry Andric  ValueType PrimaryVT = primaryvt;
111d56accc7SDimitry Andric}
112d56accc7SDimitry Andric
11306c3fb27SDimitry Andricdef FExt       : ExtInfo<"", "", [HasStdExtF], f32, FPR32, FPR32, ?, ?>;
114d56accc7SDimitry Andric
11506c3fb27SDimitry Andricdef ZfinxExt   : ExtInfo<"_INX", "RVZfinx", [HasStdExtZfinx], f32, FPR32INX, FPR32INX, ?, ?>;
116d56accc7SDimitry Andric
11706c3fb27SDimitry Andricdefvar FExts   = [FExt, ZfinxExt];
118d56accc7SDimitry Andric
1190b57cec5SDimitry Andric// Floating-point rounding mode
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andricdef FRMArg : AsmOperandClass {
1220b57cec5SDimitry Andric  let Name = "FRMArg";
1230b57cec5SDimitry Andric  let RenderMethod = "addFRMArgOperands";
12406c3fb27SDimitry Andric  let ParserMethod = "parseFRMArg";
12506c3fb27SDimitry Andric  let IsOptional = 1;
12606c3fb27SDimitry Andric  let DefaultMethod = "defaultFRMArgOp";
1270b57cec5SDimitry Andric}
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andricdef frmarg : Operand<XLenVT> {
1300b57cec5SDimitry Andric  let ParserMatchClass = FRMArg;
1310b57cec5SDimitry Andric  let PrintMethod = "printFRMArg";
1320b57cec5SDimitry Andric  let DecoderMethod = "decodeFRMArg";
1330b57cec5SDimitry Andric}
1340b57cec5SDimitry Andric
1355f757f3fSDimitry Andric// Variants of the rounding mode operand that default to 'rne'. This is used
1365f757f3fSDimitry Andric// for historical/legacy reasons. fcvt functions where the rounding mode
1375f757f3fSDimitry Andric// doesn't affect the output originally always set it to 0b000 ('rne'). As old
1385f757f3fSDimitry Andric// versions of LLVM and GCC will fail to decode versions of these instructions
1395f757f3fSDimitry Andric// with the rounding mode set to something other than 'rne', we retain this
1405f757f3fSDimitry Andric// default.
1415f757f3fSDimitry Andricdef FRMArgLegacy : AsmOperandClass {
1425f757f3fSDimitry Andric  let Name = "FRMArgLegacy";
1435f757f3fSDimitry Andric  let RenderMethod = "addFRMArgOperands";
1445f757f3fSDimitry Andric  let ParserMethod = "parseFRMArg";
1455f757f3fSDimitry Andric  let IsOptional = 1;
1465f757f3fSDimitry Andric  let DefaultMethod = "defaultFRMArgLegacyOp";
1475f757f3fSDimitry Andric}
1485f757f3fSDimitry Andric
1495f757f3fSDimitry Andricdef frmarglegacy : Operand<XLenVT> {
1505f757f3fSDimitry Andric  let ParserMatchClass = FRMArgLegacy;
1515f757f3fSDimitry Andric  let PrintMethod = "printFRMArgLegacy";
1525f757f3fSDimitry Andric  let DecoderMethod = "decodeFRMArg";
1535f757f3fSDimitry Andric}
1545f757f3fSDimitry Andric
1550b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1560b57cec5SDimitry Andric// Instruction class templates
1570b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1580b57cec5SDimitry Andric
15904eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
16006c3fb27SDimitry Andricclass FPLoad_r<bits<3> funct3, string opcodestr, DAGOperand rty,
16104eeddc0SDimitry Andric               SchedWrite sw>
16204eeddc0SDimitry Andric    : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd),
163bdd1243dSDimitry Andric              (ins GPRMem:$rs1, simm12:$imm12),
16404eeddc0SDimitry Andric              opcodestr, "$rd, ${imm12}(${rs1})">,
16504eeddc0SDimitry Andric      Sched<[sw, ReadFMemBase]>;
16604eeddc0SDimitry Andric
16704eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
16806c3fb27SDimitry Andricclass FPStore_r<bits<3> funct3, string opcodestr, DAGOperand rty,
16904eeddc0SDimitry Andric                SchedWrite sw>
17004eeddc0SDimitry Andric    : RVInstS<funct3, OPC_STORE_FP, (outs),
171bdd1243dSDimitry Andric              (ins rty:$rs2, GPRMem:$rs1, simm12:$imm12),
17204eeddc0SDimitry Andric              opcodestr, "$rs2, ${imm12}(${rs1})">,
173bdd1243dSDimitry Andric      Sched<[sw, ReadFStoreData, ReadFMemBase]>;
17404eeddc0SDimitry Andric
1750eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
17681ad6265SDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1, isCommutable = 1 in
1770eae32dcSDimitry Andricclass FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,
178d56accc7SDimitry Andric                    DAGOperand rty>
1790eae32dcSDimitry Andric    : RVInstR4Frm<funct2, opcode, (outs rty:$rd),
1800eae32dcSDimitry Andric                  (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm),
18106c3fb27SDimitry Andric                  opcodestr, "$rd, $rs1, $rs2, $rs3$frm">;
1820b57cec5SDimitry Andric
183d56accc7SDimitry Andricmulticlass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,
18406c3fb27SDimitry Andric                           string opcodestr, ExtInfo Ext> {
185d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
18606c3fb27SDimitry Andric  def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.PrimaryTy>;
187d56accc7SDimitry Andric}
1880b57cec5SDimitry Andric
1890eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
1900eae32dcSDimitry Andricclass FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
19181ad6265SDimitry Andric               DAGOperand rty, bit Commutable>
1920eae32dcSDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd),
19381ad6265SDimitry Andric              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
19481ad6265SDimitry Andric  let isCommutable = Commutable;
19581ad6265SDimitry Andric}
196d56accc7SDimitry Andricmulticlass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
19706c3fb27SDimitry Andric                      ExtInfo Ext, bit Commutable = 0> {
198d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
19906c3fb27SDimitry Andric  def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
2000eae32dcSDimitry Andric}
2010b57cec5SDimitry Andric
2020eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
2030eae32dcSDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1 in
20481ad6265SDimitry Andricclass FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty,
20581ad6265SDimitry Andric                   bit Commutable>
206d56accc7SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd),
207d56accc7SDimitry Andric                 (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr,
20806c3fb27SDimitry Andric                  "$rd, $rs1, $rs2$frm"> {
20981ad6265SDimitry Andric  let isCommutable = Commutable;
21081ad6265SDimitry Andric}
211d56accc7SDimitry Andricmulticlass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,
21206c3fb27SDimitry Andric                          ExtInfo Ext, bit Commutable = 0> {
213d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
21406c3fb27SDimitry Andric  def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.PrimaryTy, Commutable>;
215d56accc7SDimitry Andric}
216d56accc7SDimitry Andric
217d56accc7SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
218d56accc7SDimitry Andricclass FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
219d56accc7SDimitry Andric                  DAGOperand rdty, DAGOperand rs1ty, string opcodestr>
220d56accc7SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
221d56accc7SDimitry Andric              opcodestr, "$rd, $rs1"> {
222d56accc7SDimitry Andric  let rs2 = rs2val;
223d56accc7SDimitry Andric}
224d56accc7SDimitry Andricmulticlass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
22506c3fb27SDimitry Andric                         ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
22606c3fb27SDimitry Andric                         string opcodestr> {
227d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
22806c3fb27SDimitry Andric  def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, rdty, rs1ty, opcodestr>;
229d56accc7SDimitry Andric}
230d56accc7SDimitry Andric
231d56accc7SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
232d56accc7SDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1 in
233d56accc7SDimitry Andricclass FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
234d56accc7SDimitry Andric                      DAGOperand rs1ty, string opcodestr>
2350b57cec5SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
2360eae32dcSDimitry Andric                 (ins rs1ty:$rs1, frmarg:$frm), opcodestr,
23706c3fb27SDimitry Andric                  "$rd, $rs1$frm"> {
2380eae32dcSDimitry Andric  let rs2 = rs2val;
2390eae32dcSDimitry Andric}
240d56accc7SDimitry Andricmulticlass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,
24106c3fb27SDimitry Andric                             ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
24206c3fb27SDimitry Andric                             string opcodestr, list<Predicate> ExtraPreds = []> {
24306c3fb27SDimitry Andric  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
24406c3fb27SDimitry Andric      DecoderNamespace = Ext.Space in
24506c3fb27SDimitry Andric  def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, rdty, rs1ty,
246d56accc7SDimitry Andric                                   opcodestr>;
247d56accc7SDimitry Andric}
2480b57cec5SDimitry Andric
249bdd1243dSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
2505f757f3fSDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1 in
2515f757f3fSDimitry Andricclass FPUnaryOp_r_frmlegacy<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
2525f757f3fSDimitry Andric                            DAGOperand rs1ty, string opcodestr>
2535f757f3fSDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
2545f757f3fSDimitry Andric                 (ins rs1ty:$rs1, frmarglegacy:$frm), opcodestr,
2555f757f3fSDimitry Andric                  "$rd, $rs1$frm"> {
2565f757f3fSDimitry Andric  let rs2 = rs2val;
2575f757f3fSDimitry Andric}
2585f757f3fSDimitry Andricmulticlass FPUnaryOp_r_frmlegacy_m<bits<7> funct7, bits<5> rs2val,
2595f757f3fSDimitry Andric                                   ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
2605f757f3fSDimitry Andric                                   string opcodestr, list<Predicate> ExtraPreds = []> {
2615f757f3fSDimitry Andric  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
2625f757f3fSDimitry Andric      DecoderNamespace = Ext.Space in
2635f757f3fSDimitry Andric  def Ext.Suffix : FPUnaryOp_r_frmlegacy<funct7, rs2val, rdty, rs1ty,
2645f757f3fSDimitry Andric                                         opcodestr>;
2655f757f3fSDimitry Andric}
2665f757f3fSDimitry Andric
2675f757f3fSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
268bdd1243dSDimitry Andric    IsSignExtendingOpW = 1 in
2690eae32dcSDimitry Andricclass FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
27006c3fb27SDimitry Andric               DAGOperand rty, bit Commutable = 0>
2710eae32dcSDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd),
27281ad6265SDimitry Andric              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
27381ad6265SDimitry Andric  let isCommutable = Commutable;
27481ad6265SDimitry Andric}
275d56accc7SDimitry Andricmulticlass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
27606c3fb27SDimitry Andric                      ExtInfo Ext, bit Commutable = 0> {
277d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
27806c3fb27SDimitry Andric  def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
279d56accc7SDimitry Andric}
2800b57cec5SDimitry Andric
28106c3fb27SDimitry Andricclass PseudoFROUND<DAGOperand Ty, ValueType vt>
282bdd1243dSDimitry Andric    : Pseudo<(outs Ty:$rd), (ins Ty:$rs1, Ty:$rs2, ixlenimm:$rm),
28306c3fb27SDimitry Andric      [(set Ty:$rd, (vt (riscv_fround Ty:$rs1, Ty:$rs2, timm:$rm)))]> {
284bdd1243dSDimitry Andric  let hasSideEffects = 0;
285bdd1243dSDimitry Andric  let mayLoad = 0;
286bdd1243dSDimitry Andric  let mayStore = 0;
287bdd1243dSDimitry Andric  let usesCustomInserter = 1;
288bdd1243dSDimitry Andric  let mayRaiseFPException = 1;
289bdd1243dSDimitry Andric}
290bdd1243dSDimitry Andric
2910b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2920b57cec5SDimitry Andric// Instructions
2930b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
29604eeddc0SDimitry Andricdef FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than
2990b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction
3000b57cec5SDimitry Andric// encoding.
30104eeddc0SDimitry Andricdef FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;
302d56accc7SDimitry Andric} // Predicates = [HasStdExtF]
3030b57cec5SDimitry Andric
30406c3fb27SDimitry Andricforeach Ext = FExts in {
3055f757f3fSDimitry Andric  let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32Addend] in {
30606c3fb27SDimitry Andric    defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  Ext>;
30706c3fb27SDimitry Andric    defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  Ext>;
30806c3fb27SDimitry Andric    defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", Ext>;
30906c3fb27SDimitry Andric    defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", Ext>;
3100b57cec5SDimitry Andric  }
3110eae32dcSDimitry Andric
312bdd1243dSDimitry Andric  let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {
31306c3fb27SDimitry Andric    defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, Commutable=1>;
31406c3fb27SDimitry Andric    defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>;
315d56accc7SDimitry Andric  }
31606c3fb27SDimitry Andric
317d56accc7SDimitry Andric  let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
31806c3fb27SDimitry Andric  defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, Commutable=1>;
3190eae32dcSDimitry Andric
320d56accc7SDimitry Andric  let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
32106c3fb27SDimitry Andric  defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>;
3220eae32dcSDimitry Andric
32306c3fb27SDimitry Andric  defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, Ext, Ext.PrimaryTy,
32406c3fb27SDimitry Andric                                   Ext.PrimaryTy, "fsqrt.s">,
3250eae32dcSDimitry Andric                 Sched<[WriteFSqrt32, ReadFSqrt32]>;
3260b57cec5SDimitry Andric
3270eae32dcSDimitry Andric  let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
3280eae32dcSDimitry Andric      mayRaiseFPException = 0 in {
32906c3fb27SDimitry Andric    defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  Ext>;
33006c3fb27SDimitry Andric    defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", Ext>;
33106c3fb27SDimitry Andric    defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", Ext>;
3320b57cec5SDimitry Andric  }
3330eae32dcSDimitry Andric
3340eae32dcSDimitry Andric  let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
33506c3fb27SDimitry Andric    defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, Commutable=1>;
33606c3fb27SDimitry Andric    defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, Commutable=1>;
3370eae32dcSDimitry Andric  }
3380eae32dcSDimitry Andric
339bdd1243dSDimitry Andric  let IsSignExtendingOpW = 1 in
34006c3fb27SDimitry Andric  defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, Ext, GPR, Ext.PrimaryTy,
34106c3fb27SDimitry Andric                                    "fcvt.w.s">,
3420eae32dcSDimitry Andric                  Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
3430b57cec5SDimitry Andric
344bdd1243dSDimitry Andric  let IsSignExtendingOpW = 1 in
34506c3fb27SDimitry Andric  defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, Ext, GPR, Ext.PrimaryTy,
34606c3fb27SDimitry Andric                                     "fcvt.wu.s">,
3470eae32dcSDimitry Andric                   Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
34806c3fb27SDimitry Andric
34906c3fb27SDimitry Andric  let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
35006c3fb27SDimitry Andric  defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, Commutable=1>;
35106c3fb27SDimitry Andric  defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>;
35206c3fb27SDimitry Andric  defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>;
35306c3fb27SDimitry Andric  }
35406c3fb27SDimitry Andric
35506c3fb27SDimitry Andric  let mayRaiseFPException = 0 in
35606c3fb27SDimitry Andric  defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
35706c3fb27SDimitry Andric                                "fclass.s">,
35806c3fb27SDimitry Andric                  Sched<[WriteFClass32, ReadFClass32]>;
35906c3fb27SDimitry Andric
36006c3fb27SDimitry Andric  defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, Ext, Ext.PrimaryTy, GPR,
36106c3fb27SDimitry Andric                                    "fcvt.s.w">,
36206c3fb27SDimitry Andric                  Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
36306c3fb27SDimitry Andric
36406c3fb27SDimitry Andric  defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, Ext, Ext.PrimaryTy, GPR,
36506c3fb27SDimitry Andric                                     "fcvt.s.wu">,
36606c3fb27SDimitry Andric                   Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
36706c3fb27SDimitry Andric
36806c3fb27SDimitry Andric  defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, Ext, GPR, Ext.PrimaryTy,
36906c3fb27SDimitry Andric                                     "fcvt.l.s", [IsRV64]>,
37006c3fb27SDimitry Andric                   Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
37106c3fb27SDimitry Andric
37206c3fb27SDimitry Andric  defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, Ext, GPR, Ext.PrimaryTy,
37306c3fb27SDimitry Andric                                      "fcvt.lu.s", [IsRV64]>,
37406c3fb27SDimitry Andric                    Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
37506c3fb27SDimitry Andric
37606c3fb27SDimitry Andric  defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, Ext, Ext.PrimaryTy, GPR,
37706c3fb27SDimitry Andric                                    "fcvt.s.l", [IsRV64]>,
37806c3fb27SDimitry Andric                  Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
37906c3fb27SDimitry Andric
38006c3fb27SDimitry Andric  defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, Ext, Ext.PrimaryTy, GPR,
38106c3fb27SDimitry Andric                                     "fcvt.s.lu", [IsRV64]>,
38206c3fb27SDimitry Andric                   Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
38306c3fb27SDimitry Andric} // foreach Ext = FExts
3840b57cec5SDimitry Andric
385bdd1243dSDimitry Andriclet Predicates = [HasStdExtF], mayRaiseFPException = 0,
386bdd1243dSDimitry Andric    IsSignExtendingOpW = 1 in
3870eae32dcSDimitry Andricdef FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,
3880eae32dcSDimitry Andric              Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;
3890eae32dcSDimitry Andric
390bdd1243dSDimitry Andriclet Predicates = [HasStdExtF], mayRaiseFPException = 0 in
3910eae32dcSDimitry Andricdef FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,
3920eae32dcSDimitry Andric              Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
3950b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
3960b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
3990b57cec5SDimitry Andricdef : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;
4000b57cec5SDimitry Andricdef : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andricdef : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
4030b57cec5SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
4040b57cec5SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andric// fgt.s/fge.s are recognised by the GNU assembler but the canonical
4070b57cec5SDimitry Andric// flt.s/fle.s forms will always be printed. Therefore, set a zero weight.
4080b57cec5SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt",
4090b57cec5SDimitry Andric                (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
4100b57cec5SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt",
4110b57cec5SDimitry Andric                (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric// The following csr instructions actually alias instructions from the base ISA.
4140b57cec5SDimitry Andric// However, it only makes sense to support them when the F extension is enabled.
4150b57cec5SDimitry Andric// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr".
416fe6060f1SDimitry Andricdef : InstAlias<"frcsr $rd",      (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>;
417fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>;
418fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rs",      (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 2>;
4190b57cec5SDimitry Andric
4208bcb0991SDimitry Andric// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them
4218bcb0991SDimitry Andric// zero weight.
422fe6060f1SDimitry Andricdef : InstAlias<"frsr $rd",       (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>;
423fe6060f1SDimitry Andricdef : InstAlias<"fssr $rd, $rs",  (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>;
424fe6060f1SDimitry Andricdef : InstAlias<"fssr $rs",       (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 0>;
4258bcb0991SDimitry Andric
426fe6060f1SDimitry Andricdef : InstAlias<"frrm $rd",        (CSRRS  GPR:$rd, SysRegFRM.Encoding, X0), 2>;
427fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rd, $rs",   (CSRRW  GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>;
428fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rs",        (CSRRW       X0, SysRegFRM.Encoding, GPR:$rs), 2>;
429fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>;
430fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $imm",      (CSRRWI      X0, SysRegFRM.Encoding, uimm5:$imm), 2>;
4310b57cec5SDimitry Andric
432fe6060f1SDimitry Andricdef : InstAlias<"frflags $rd",        (CSRRS  GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>;
433fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rd, $rs",   (CSRRW  GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>;
434fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rs",        (CSRRW       X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>;
435fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>;
436fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>;
4370b57cec5SDimitry Andric
4380b57cec5SDimitry Andric// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both
4390b57cec5SDimitry Andric// spellings should be supported by standard tools.
4400b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.s.x", "fmv.w.x">;
4410b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.x.s", "fmv.x.w">;
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andricdef PseudoFLW  : PseudoFloatLoad<"flw", FPR32>;
4440b57cec5SDimitry Andricdef PseudoFSW  : PseudoStore<"fsw", FPR32>;
44504eeddc0SDimitry Andriclet usesCustomInserter = 1 in {
44604eeddc0SDimitry Andricdef PseudoQuietFLE_S : PseudoQuietFCMP<FPR32>;
44704eeddc0SDimitry Andricdef PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>;
44804eeddc0SDimitry Andric}
4490b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
4500b57cec5SDimitry Andric
451d56accc7SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
452d56accc7SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
453d56accc7SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
454d56accc7SDimitry Andric
455d56accc7SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt",
456d56accc7SDimitry Andric                (FLT_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
457d56accc7SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt",
458d56accc7SDimitry Andric                (FLE_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
45906c3fb27SDimitry Andriclet usesCustomInserter = 1 in {
46006c3fb27SDimitry Andricdef PseudoQuietFLE_S_INX : PseudoQuietFCMP<FPR32INX>;
46106c3fb27SDimitry Andricdef PseudoQuietFLT_S_INX : PseudoQuietFCMP<FPR32INX>;
46206c3fb27SDimitry Andric}
463d56accc7SDimitry Andric} // Predicates = [HasStdExtZfinx]
464d56accc7SDimitry Andric
4650b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4660b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
4670b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4680b57cec5SDimitry Andric
46906c3fb27SDimitry Andricdefvar FRM_RNE = 0b000;
47006c3fb27SDimitry Andricdefvar FRM_RTZ = 0b001;
47106c3fb27SDimitry Andricdefvar FRM_RDN = 0b010;
47206c3fb27SDimitry Andricdefvar FRM_RUP = 0b011;
47306c3fb27SDimitry Andricdefvar FRM_RMM = 0b100;
47406c3fb27SDimitry Andricdefvar FRM_DYN = 0b111;
47506c3fb27SDimitry Andric
4765ffd83dbSDimitry Andric/// Floating point constants
4775ffd83dbSDimitry Andricdef fpimm0    : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
4785ffd83dbSDimitry Andric
4790b57cec5SDimitry Andric/// Generic pattern classes
48006c3fb27SDimitry Andricclass PatSetCC<DAGOperand Ty, SDPatternOperator OpNode, CondCode Cond,
48106c3fb27SDimitry Andric               RVInst Inst, ValueType vt>
48206c3fb27SDimitry Andric    : Pat<(XLenVT (OpNode (vt Ty:$rs1), Ty:$rs2, Cond)), (Inst $rs1, $rs2)>;
48306c3fb27SDimitry Andricmulticlass PatSetCC_m<SDPatternOperator OpNode, CondCode Cond,
4845f757f3fSDimitry Andric                      RVInst Inst, ExtInfo Ext> {
48506c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
48606c3fb27SDimitry Andric  def Ext.Suffix : PatSetCC<Ext.PrimaryTy, OpNode, Cond,
4875f757f3fSDimitry Andric                            !cast<RVInst>(Inst#Ext.Suffix), Ext.PrimaryVT>;
48806c3fb27SDimitry Andric}
48904eeddc0SDimitry Andric
49081ad6265SDimitry Andricclass PatFprFpr<SDPatternOperator OpNode, RVInstR Inst,
49106c3fb27SDimitry Andric                DAGOperand RegTy, ValueType vt>
49206c3fb27SDimitry Andric    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2)>;
49306c3fb27SDimitry Andricmulticlass PatFprFpr_m<SDPatternOperator OpNode, RVInstR Inst,
49406c3fb27SDimitry Andric                       ExtInfo Ext> {
49506c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
49606c3fb27SDimitry Andric  def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),
49706c3fb27SDimitry Andric                             Ext.PrimaryTy, Ext.PrimaryVT>;
49806c3fb27SDimitry Andric}
4990b57cec5SDimitry Andric
50081ad6265SDimitry Andricclass PatFprFprDynFrm<SDPatternOperator OpNode, RVInstRFrm Inst,
50106c3fb27SDimitry Andric                      DAGOperand RegTy, ValueType vt>
50206c3fb27SDimitry Andric    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2, FRM_DYN)>;
50306c3fb27SDimitry Andricmulticlass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,
50406c3fb27SDimitry Andric                             ExtInfo Ext> {
50506c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
50606c3fb27SDimitry Andric  def Ext.Suffix : PatFprFprDynFrm<OpNode,
50706c3fb27SDimitry Andric                                   !cast<RVInstRFrm>(Inst#Ext.Suffix),
50806c3fb27SDimitry Andric                                   Ext.PrimaryTy, Ext.PrimaryVT>;
50906c3fb27SDimitry Andric}
5105ffd83dbSDimitry Andric
5110b57cec5SDimitry Andric/// Float conversion operations
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so
5140b57cec5SDimitry Andric// are defined later.
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric/// Float arithmetic operations
51706c3fb27SDimitry Andricforeach Ext = FExts in {
51806c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fadd, FADD_S, Ext>;
51906c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, Ext>;
52006c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, Ext>;
52106c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, Ext>;
52206c3fb27SDimitry Andric}
5230b57cec5SDimitry Andric
52406c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
52506c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;
5260b57cec5SDimitry Andric
5270b57cec5SDimitry Andricdef : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;
5280b57cec5SDimitry Andricdef : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;
5290b57cec5SDimitry Andric
5305f757f3fSDimitry Andricdef : Pat<(riscv_fclass FPR32:$rs1), (FCLASS_S $rs1)>;
53106c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
53206c3fb27SDimitry Andric
53306c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
53406c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR32INX:$rs1), (FSQRT_S_INX FPR32INX:$rs1, FRM_DYN)>;
53506c3fb27SDimitry Andric
53606c3fb27SDimitry Andricdef : Pat<(fneg FPR32INX:$rs1), (FSGNJN_S_INX $rs1, $rs1)>;
53706c3fb27SDimitry Andricdef : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>;
53806c3fb27SDimitry Andric
5395f757f3fSDimitry Andricdef : Pat<(riscv_fclass FPR32INX:$rs1), (FCLASS_S_INX $rs1)>;
54006c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
54106c3fb27SDimitry Andric
54206c3fb27SDimitry Andricforeach Ext = FExts in
54306c3fb27SDimitry Andricdefm : PatFprFpr_m<fcopysign, FSGNJ_S, Ext>;
54406c3fb27SDimitry Andric
54506c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
5460b57cec5SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3
5490eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3),
55006c3fb27SDimitry Andric          (FMADD_S $rs1, $rs2, $rs3, FRM_DYN)>;
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3
5530eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)),
55406c3fb27SDimitry Andric          (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3
5570eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3),
55806c3fb27SDimitry Andric          (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3
5610eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)),
56206c3fb27SDimitry Andric          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5630b57cec5SDimitry Andric
56481ad6265SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
56581ad6265SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR32:$rs1, FPR32:$rs2, FPR32:$rs3)),
56606c3fb27SDimitry Andric          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
56706c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
56806c3fb27SDimitry Andric
56906c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
57006c3fb27SDimitry Andricdef : Pat<(fcopysign FPR32INX:$rs1, (fneg FPR32INX:$rs2)), (FSGNJN_S_INX $rs1, $rs2)>;
57106c3fb27SDimitry Andric
57206c3fb27SDimitry Andric// fmadd: rs1 * rs2 + rs3
57306c3fb27SDimitry Andricdef : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3),
57406c3fb27SDimitry Andric          (FMADD_S_INX $rs1, $rs2, $rs3, FRM_DYN)>;
57506c3fb27SDimitry Andric
57606c3fb27SDimitry Andric// fmsub: rs1 * rs2 - rs3
57706c3fb27SDimitry Andricdef : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
57806c3fb27SDimitry Andric          (FMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
57906c3fb27SDimitry Andric
58006c3fb27SDimitry Andric// fnmsub: -rs1 * rs2 + rs3
58106c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, FPR32INX:$rs3),
58206c3fb27SDimitry Andric          (FNMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
58306c3fb27SDimitry Andric
58406c3fb27SDimitry Andric// fnmadd: -rs1 * rs2 - rs3
58506c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
58606c3fb27SDimitry Andric          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
58706c3fb27SDimitry Andric
58806c3fb27SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
58906c3fb27SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3)),
59006c3fb27SDimitry Andric          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
59106c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
59281ad6265SDimitry Andric
593fe6060f1SDimitry Andric// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
594fe6060f1SDimitry Andric// LLVM's fminnum and fmaxnum
5950b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
59606c3fb27SDimitry Andricforeach Ext = FExts in {
59706c3fb27SDimitry Andric  defm : PatFprFpr_m<fminnum, FMIN_S, Ext>;
59806c3fb27SDimitry Andric  defm : PatFprFpr_m<fmaxnum, FMAX_S, Ext>;
59906c3fb27SDimitry Andric  defm : PatFprFpr_m<riscv_fmin, FMIN_S, Ext>;
60006c3fb27SDimitry Andric  defm : PatFprFpr_m<riscv_fmax, FMAX_S, Ext>;
60106c3fb27SDimitry Andric}
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric/// Setcc
60404eeddc0SDimitry Andric// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
60504eeddc0SDimitry Andric// strict versions of those.
6060b57cec5SDimitry Andric
60704eeddc0SDimitry Andric// Match non-signaling FEQ_S
60806c3fb27SDimitry Andricforeach Ext = FExts in {
6095f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            Ext>;
6105f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            Ext>;
6115f757f3fSDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, Ext>;
6125f757f3fSDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, Ext>;
6135f757f3fSDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, Ext>;
6145f757f3fSDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, Ext>;
61506c3fb27SDimitry Andric}
61604eeddc0SDimitry Andric
61706c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
61804eeddc0SDimitry Andric// Match signaling FEQ_S
61906c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETEQ)),
62004eeddc0SDimitry Andric          (AND (FLE_S $rs1, $rs2),
62104eeddc0SDimitry Andric               (FLE_S $rs2, $rs1))>;
62206c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETOEQ)),
62304eeddc0SDimitry Andric          (AND (FLE_S $rs1, $rs2),
62404eeddc0SDimitry Andric               (FLE_S $rs2, $rs1))>;
62504eeddc0SDimitry Andric// If both operands are the same, use a single FLE.
62606c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETEQ)),
62704eeddc0SDimitry Andric          (FLE_S $rs1, $rs1)>;
62806c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETOEQ)),
62904eeddc0SDimitry Andric          (FLE_S $rs1, $rs1)>;
63006c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
63104eeddc0SDimitry Andric
63206c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
63306c3fb27SDimitry Andric// Match signaling FEQ_S
63406c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETEQ)),
63506c3fb27SDimitry Andric          (AND (FLE_S_INX $rs1, $rs2),
63606c3fb27SDimitry Andric               (FLE_S_INX $rs2, $rs1))>;
63706c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETOEQ)),
63806c3fb27SDimitry Andric          (AND (FLE_S_INX $rs1, $rs2),
63906c3fb27SDimitry Andric               (FLE_S_INX $rs2, $rs1))>;
64006c3fb27SDimitry Andric// If both operands are the same, use a single FLE.
64106c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETEQ)),
64206c3fb27SDimitry Andric          (FLE_S_INX $rs1, $rs1)>;
64306c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETOEQ)),
64406c3fb27SDimitry Andric          (FLE_S_INX $rs1, $rs1)>;
64506c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
6460b57cec5SDimitry Andric
64706c3fb27SDimitry Andricforeach Ext = FExts in {
6485f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, Ext>;
6495f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, Ext>;
6505f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, Ext>;
6515f757f3fSDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, Ext>;
65206c3fb27SDimitry Andric}
653bdd1243dSDimitry Andric
65406c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
65506c3fb27SDimitry Andricdefm Select_FPR32 : SelectCC_GPR_rrirr<FPR32, f32>;
65606c3fb27SDimitry Andric
65706c3fb27SDimitry Andricdef PseudoFROUND_S : PseudoFROUND<FPR32, f32>;
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andric/// Loads
6600b57cec5SDimitry Andric
66106c3fb27SDimitry Andricdef : LdPat<load, FLW, f32>;
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric/// Stores
6640b57cec5SDimitry Andric
66506c3fb27SDimitry Andricdef : StPat<store, FSW, FPR32, f32>;
6660b57cec5SDimitry Andric
6670b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
6680b57cec5SDimitry Andric
66906c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
67006c3fb27SDimitry Andricdefm Select_FPR32INX : SelectCC_GPR_rrirr<FPR32INX, f32>;
67106c3fb27SDimitry Andric
67206c3fb27SDimitry Andricdef PseudoFROUND_S_INX : PseudoFROUND<FPR32INX, f32>;
67306c3fb27SDimitry Andric
67406c3fb27SDimitry Andric/// Loads
67506c3fb27SDimitry Andricdef : Pat<(f32 (load (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))),
67606c3fb27SDimitry Andric          (COPY_TO_REGCLASS (LW GPR:$rs1, simm12:$imm12), GPRF32)>;
67706c3fb27SDimitry Andric
67806c3fb27SDimitry Andric/// Stores
67906c3fb27SDimitry Andricdef : Pat<(store (f32 FPR32INX:$rs2), (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12)),
68006c3fb27SDimitry Andric          (SW (COPY_TO_REGCLASS FPR32INX:$rs2, GPR), GPR:$rs1, simm12:$imm12)>;
68106c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
68206c3fb27SDimitry Andric
6835f757f3fSDimitry Andriclet Predicates = [HasStdExtF] in {
684e8d8bef9SDimitry Andric// Moves (no conversion)
685fe6060f1SDimitry Andricdef : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>;
686fe6060f1SDimitry Andricdef : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>;
6875f757f3fSDimitry Andric} // Predicates = [HasStdExtF]
688e8d8bef9SDimitry Andric
6895f757f3fSDimitry Andriclet Predicates = [HasStdExtZfinx] in {
69006c3fb27SDimitry Andric// Moves (no conversion)
69106c3fb27SDimitry Andricdef : Pat<(f32 (bitconvert (i32 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPRF32)>;
69206c3fb27SDimitry Andricdef : Pat<(i32 (bitconvert FPR32INX:$rs1)), (COPY_TO_REGCLASS FPR32INX:$rs1, GPR)>;
6935f757f3fSDimitry Andric} // Predicates = [HasStdExtZfinx]
69406c3fb27SDimitry Andric
6955f757f3fSDimitry Andriclet Predicates = [HasStdExtF] in {
6960b57cec5SDimitry Andric// float->[u]int. Round-to-zero must be used.
69706c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RTZ)>;
69806c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, FRM_RTZ)>;
699fe6060f1SDimitry Andric
700349cc55cSDimitry Andric// Saturating float->[u]int32.
70104eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_W_S $rs1, timm:$frm)>;
70204eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_WU_S $rs1, timm:$frm)>;
703349cc55cSDimitry Andric
704fe6060f1SDimitry Andric// float->int32 with current rounding mode.
70506c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_DYN)>;
706fe6060f1SDimitry Andric
707fe6060f1SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero.
70806c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RMM)>;
7090b57cec5SDimitry Andric
7100b57cec5SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode.
71106c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, FRM_DYN)>;
71206c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, FRM_DYN)>;
7135f757f3fSDimitry Andric} // Predicates = [HasStdExtF]
7140b57cec5SDimitry Andric
7155f757f3fSDimitry Andriclet Predicates = [HasStdExtZfinx] in {
71606c3fb27SDimitry Andric// float->[u]int. Round-to-zero must be used.
71706c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RTZ)>;
71806c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_WU_S_INX $rs1, FRM_RTZ)>;
71906c3fb27SDimitry Andric
72006c3fb27SDimitry Andric// Saturating float->[u]int32.
72106c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_W_S_INX $rs1, timm:$frm)>;
72206c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_WU_S_INX $rs1, timm:$frm)>;
72306c3fb27SDimitry Andric
72406c3fb27SDimitry Andric// float->int32 with current rounding mode.
72506c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_DYN)>;
72606c3fb27SDimitry Andric
72706c3fb27SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero.
72806c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RMM)>;
72906c3fb27SDimitry Andric
73006c3fb27SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode.
73106c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W_INX $rs1, FRM_DYN)>;
73206c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
7335f757f3fSDimitry Andric} // Predicates = [HasStdExtZfinx]
73406c3fb27SDimitry Andric
7350b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in {
736e8d8bef9SDimitry Andric// Moves (no conversion)
7370b57cec5SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>;
7380b57cec5SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;
7390b57cec5SDimitry Andric
740fe6060f1SDimitry Andric// Use target specific isd nodes to help us remember the result is sign
741fe6060f1SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
742fe6060f1SDimitry Andric// duplicated if it has another user that didn't need the sign_extend.
74304eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR32:$rs1, timm:$frm),  (FCVT_W_S $rs1, timm:$frm)>;
74404eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR32:$rs1, timm:$frm), (FCVT_WU_S $rs1, timm:$frm)>;
7450b57cec5SDimitry Andric
746fe6060f1SDimitry Andric// float->[u]int64. Round-to-zero must be used.
74706c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RTZ)>;
74806c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, FRM_RTZ)>;
749fe6060f1SDimitry Andric
750349cc55cSDimitry Andric// Saturating float->[u]int64.
75104eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_L_S $rs1, timm:$frm)>;
75204eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_LU_S $rs1, timm:$frm)>;
753349cc55cSDimitry Andric
754fe6060f1SDimitry Andric// float->int64 with current rounding mode.
75506c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
75606c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
757fe6060f1SDimitry Andric
758fe6060f1SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero.
75906c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
76006c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
7610b57cec5SDimitry Andric
7620b57cec5SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode.
76306c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, FRM_DYN)>;
76406c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, FRM_DYN)>;
76506c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, FRM_DYN)>;
76606c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, FRM_DYN)>;
7670b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64]
76806c3fb27SDimitry Andric
76906c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx, IsRV64] in {
77006c3fb27SDimitry Andric// Moves (no conversion)
77106c3fb27SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (COPY_TO_REGCLASS GPR:$src, GPRF32)>;
77206c3fb27SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 GPRF32:$src), (COPY_TO_REGCLASS GPRF32:$src, GPR)>;
77306c3fb27SDimitry Andric
77406c3fb27SDimitry Andric// Use target specific isd nodes to help us remember the result is sign
77506c3fb27SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
77606c3fb27SDimitry Andric// duplicated if it has another user that didn't need the sign_extend.
77706c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR32INX:$rs1, timm:$frm),  (FCVT_W_S_INX $rs1, timm:$frm)>;
77806c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR32INX:$rs1, timm:$frm), (FCVT_WU_S_INX $rs1, timm:$frm)>;
77906c3fb27SDimitry Andric
78006c3fb27SDimitry Andric// float->[u]int64. Round-to-zero must be used.
78106c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RTZ)>;
78206c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_LU_S_INX $rs1, FRM_RTZ)>;
78306c3fb27SDimitry Andric
78406c3fb27SDimitry Andric// Saturating float->[u]int64.
78506c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_L_S_INX $rs1, timm:$frm)>;
78606c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_LU_S_INX $rs1, timm:$frm)>;
78706c3fb27SDimitry Andric
78806c3fb27SDimitry Andric// float->int64 with current rounding mode.
78906c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
79006c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
79106c3fb27SDimitry Andric
79206c3fb27SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero.
79306c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
79406c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
79506c3fb27SDimitry Andric
79606c3fb27SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode.
79706c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W_INX $rs1, FRM_DYN)>;
79806c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
79906c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L_INX $rs1, FRM_DYN)>;
80006c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU_INX $rs1, FRM_DYN)>;
80106c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx, IsRV64]
802