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>]>;
3206c3fb27SDimitry Andricdef SDT_RISCVFPCLASS
3306c3fb27SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>;
3406c3fb27SDimitry Andric
3506c3fb27SDimitry Andricdef riscv_fpclass
3606c3fb27SDimitry Andric    : SDNode<"RISCVISD::FPCLASS", SDT_RISCVFPCLASS>;
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
1350b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1360b57cec5SDimitry Andric// Instruction class templates
1370b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1380b57cec5SDimitry Andric
13904eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
14006c3fb27SDimitry Andricclass FPLoad_r<bits<3> funct3, string opcodestr, DAGOperand rty,
14104eeddc0SDimitry Andric               SchedWrite sw>
14204eeddc0SDimitry Andric    : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd),
143bdd1243dSDimitry Andric              (ins GPRMem:$rs1, simm12:$imm12),
14404eeddc0SDimitry Andric              opcodestr, "$rd, ${imm12}(${rs1})">,
14504eeddc0SDimitry Andric      Sched<[sw, ReadFMemBase]>;
14604eeddc0SDimitry Andric
14704eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
14806c3fb27SDimitry Andricclass FPStore_r<bits<3> funct3, string opcodestr, DAGOperand rty,
14904eeddc0SDimitry Andric                SchedWrite sw>
15004eeddc0SDimitry Andric    : RVInstS<funct3, OPC_STORE_FP, (outs),
151bdd1243dSDimitry Andric              (ins rty:$rs2, GPRMem:$rs1, simm12:$imm12),
15204eeddc0SDimitry Andric              opcodestr, "$rs2, ${imm12}(${rs1})">,
153bdd1243dSDimitry Andric      Sched<[sw, ReadFStoreData, ReadFMemBase]>;
15404eeddc0SDimitry Andric
1550eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
15681ad6265SDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1, isCommutable = 1 in
1570eae32dcSDimitry Andricclass FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,
158d56accc7SDimitry Andric                    DAGOperand rty>
1590eae32dcSDimitry Andric    : RVInstR4Frm<funct2, opcode, (outs rty:$rd),
1600eae32dcSDimitry Andric                  (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm),
16106c3fb27SDimitry Andric                  opcodestr, "$rd, $rs1, $rs2, $rs3$frm">;
1620b57cec5SDimitry Andric
163d56accc7SDimitry Andricmulticlass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,
16406c3fb27SDimitry Andric                           string opcodestr, ExtInfo Ext> {
165d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
16606c3fb27SDimitry Andric  def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.PrimaryTy>;
167d56accc7SDimitry Andric}
1680b57cec5SDimitry Andric
1690eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
1700eae32dcSDimitry Andricclass FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
17181ad6265SDimitry Andric               DAGOperand rty, bit Commutable>
1720eae32dcSDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd),
17381ad6265SDimitry Andric              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
17481ad6265SDimitry Andric  let isCommutable = Commutable;
17581ad6265SDimitry Andric}
176d56accc7SDimitry Andricmulticlass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
17706c3fb27SDimitry Andric                      ExtInfo Ext, bit Commutable = 0> {
178d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
17906c3fb27SDimitry Andric  def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
1800eae32dcSDimitry Andric}
1810b57cec5SDimitry Andric
1820eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
1830eae32dcSDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1 in
18481ad6265SDimitry Andricclass FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty,
18581ad6265SDimitry Andric                   bit Commutable>
186d56accc7SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd),
187d56accc7SDimitry Andric                 (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr,
18806c3fb27SDimitry Andric                  "$rd, $rs1, $rs2$frm"> {
18981ad6265SDimitry Andric  let isCommutable = Commutable;
19081ad6265SDimitry Andric}
191d56accc7SDimitry Andricmulticlass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,
19206c3fb27SDimitry Andric                          ExtInfo Ext, bit Commutable = 0> {
193d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
19406c3fb27SDimitry Andric  def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.PrimaryTy, Commutable>;
195d56accc7SDimitry Andric}
196d56accc7SDimitry Andric
197d56accc7SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
198d56accc7SDimitry Andricclass FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
199d56accc7SDimitry Andric                  DAGOperand rdty, DAGOperand rs1ty, string opcodestr>
200d56accc7SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
201d56accc7SDimitry Andric              opcodestr, "$rd, $rs1"> {
202d56accc7SDimitry Andric  let rs2 = rs2val;
203d56accc7SDimitry Andric}
204d56accc7SDimitry Andricmulticlass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
20506c3fb27SDimitry Andric                         ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
20606c3fb27SDimitry Andric                         string opcodestr> {
207d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
20806c3fb27SDimitry Andric  def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, rdty, rs1ty, opcodestr>;
209d56accc7SDimitry Andric}
210d56accc7SDimitry Andric
211d56accc7SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
212d56accc7SDimitry Andric    UseNamedOperandTable = 1, hasPostISelHook = 1 in
213d56accc7SDimitry Andricclass FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
214d56accc7SDimitry Andric                      DAGOperand rs1ty, string opcodestr>
2150b57cec5SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
2160eae32dcSDimitry Andric                 (ins rs1ty:$rs1, frmarg:$frm), opcodestr,
21706c3fb27SDimitry Andric                  "$rd, $rs1$frm"> {
2180eae32dcSDimitry Andric  let rs2 = rs2val;
2190eae32dcSDimitry Andric}
220d56accc7SDimitry Andricmulticlass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,
22106c3fb27SDimitry Andric                             ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
22206c3fb27SDimitry Andric                             string opcodestr, list<Predicate> ExtraPreds = []> {
22306c3fb27SDimitry Andric  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
22406c3fb27SDimitry Andric      DecoderNamespace = Ext.Space in
22506c3fb27SDimitry Andric  def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, rdty, rs1ty,
226d56accc7SDimitry Andric                                   opcodestr>;
227d56accc7SDimitry Andric}
2280b57cec5SDimitry Andric
229bdd1243dSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
230bdd1243dSDimitry Andric    IsSignExtendingOpW = 1 in
2310eae32dcSDimitry Andricclass FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
23206c3fb27SDimitry Andric               DAGOperand rty, bit Commutable = 0>
2330eae32dcSDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd),
23481ad6265SDimitry Andric              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
23581ad6265SDimitry Andric  let isCommutable = Commutable;
23681ad6265SDimitry Andric}
237d56accc7SDimitry Andricmulticlass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
23806c3fb27SDimitry Andric                      ExtInfo Ext, bit Commutable = 0> {
239d56accc7SDimitry Andric  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
24006c3fb27SDimitry Andric  def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
241d56accc7SDimitry Andric}
2420b57cec5SDimitry Andric
24306c3fb27SDimitry Andricclass PseudoFROUND<DAGOperand Ty, ValueType vt>
244bdd1243dSDimitry Andric    : Pseudo<(outs Ty:$rd), (ins Ty:$rs1, Ty:$rs2, ixlenimm:$rm),
24506c3fb27SDimitry Andric      [(set Ty:$rd, (vt (riscv_fround Ty:$rs1, Ty:$rs2, timm:$rm)))]> {
246bdd1243dSDimitry Andric  let hasSideEffects = 0;
247bdd1243dSDimitry Andric  let mayLoad = 0;
248bdd1243dSDimitry Andric  let mayStore = 0;
249bdd1243dSDimitry Andric  let usesCustomInserter = 1;
250bdd1243dSDimitry Andric  let mayRaiseFPException = 1;
251bdd1243dSDimitry Andric}
252bdd1243dSDimitry Andric
2530b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2540b57cec5SDimitry Andric// Instructions
2550b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
25804eeddc0SDimitry Andricdef FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than
2610b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction
2620b57cec5SDimitry Andric// encoding.
26304eeddc0SDimitry Andricdef FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;
264d56accc7SDimitry Andric} // Predicates = [HasStdExtF]
2650b57cec5SDimitry Andric
26606c3fb27SDimitry Andricforeach Ext = FExts in {
2670eae32dcSDimitry Andric  let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in {
26806c3fb27SDimitry Andric    defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  Ext>;
26906c3fb27SDimitry Andric    defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  Ext>;
27006c3fb27SDimitry Andric    defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", Ext>;
27106c3fb27SDimitry Andric    defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", Ext>;
2720b57cec5SDimitry Andric  }
2730eae32dcSDimitry Andric
274bdd1243dSDimitry Andric  let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {
27506c3fb27SDimitry Andric    defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, Commutable=1>;
27606c3fb27SDimitry Andric    defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>;
277d56accc7SDimitry Andric  }
27806c3fb27SDimitry Andric
279d56accc7SDimitry Andric  let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
28006c3fb27SDimitry Andric  defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, Commutable=1>;
2810eae32dcSDimitry Andric
282d56accc7SDimitry Andric  let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
28306c3fb27SDimitry Andric  defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>;
2840eae32dcSDimitry Andric
28506c3fb27SDimitry Andric  defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, Ext, Ext.PrimaryTy,
28606c3fb27SDimitry Andric                                   Ext.PrimaryTy, "fsqrt.s">,
2870eae32dcSDimitry Andric                 Sched<[WriteFSqrt32, ReadFSqrt32]>;
2880b57cec5SDimitry Andric
2890eae32dcSDimitry Andric  let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
2900eae32dcSDimitry Andric      mayRaiseFPException = 0 in {
29106c3fb27SDimitry Andric    defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  Ext>;
29206c3fb27SDimitry Andric    defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", Ext>;
29306c3fb27SDimitry Andric    defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", Ext>;
2940b57cec5SDimitry Andric  }
2950eae32dcSDimitry Andric
2960eae32dcSDimitry Andric  let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
29706c3fb27SDimitry Andric    defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, Commutable=1>;
29806c3fb27SDimitry Andric    defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, Commutable=1>;
2990eae32dcSDimitry Andric  }
3000eae32dcSDimitry Andric
301bdd1243dSDimitry Andric  let IsSignExtendingOpW = 1 in
30206c3fb27SDimitry Andric  defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, Ext, GPR, Ext.PrimaryTy,
30306c3fb27SDimitry Andric                                    "fcvt.w.s">,
3040eae32dcSDimitry Andric                  Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
3050b57cec5SDimitry Andric
306bdd1243dSDimitry Andric  let IsSignExtendingOpW = 1 in
30706c3fb27SDimitry Andric  defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, Ext, GPR, Ext.PrimaryTy,
30806c3fb27SDimitry Andric                                     "fcvt.wu.s">,
3090eae32dcSDimitry Andric                   Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
31006c3fb27SDimitry Andric
31106c3fb27SDimitry Andric  let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
31206c3fb27SDimitry Andric  defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, Commutable=1>;
31306c3fb27SDimitry Andric  defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>;
31406c3fb27SDimitry Andric  defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>;
31506c3fb27SDimitry Andric  }
31606c3fb27SDimitry Andric
31706c3fb27SDimitry Andric  let mayRaiseFPException = 0 in
31806c3fb27SDimitry Andric  defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
31906c3fb27SDimitry Andric                                "fclass.s">,
32006c3fb27SDimitry Andric                  Sched<[WriteFClass32, ReadFClass32]>;
32106c3fb27SDimitry Andric
32206c3fb27SDimitry Andric  defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, Ext, Ext.PrimaryTy, GPR,
32306c3fb27SDimitry Andric                                    "fcvt.s.w">,
32406c3fb27SDimitry Andric                  Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
32506c3fb27SDimitry Andric
32606c3fb27SDimitry Andric  defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, Ext, Ext.PrimaryTy, GPR,
32706c3fb27SDimitry Andric                                     "fcvt.s.wu">,
32806c3fb27SDimitry Andric                   Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
32906c3fb27SDimitry Andric
33006c3fb27SDimitry Andric  defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, Ext, GPR, Ext.PrimaryTy,
33106c3fb27SDimitry Andric                                     "fcvt.l.s", [IsRV64]>,
33206c3fb27SDimitry Andric                   Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
33306c3fb27SDimitry Andric
33406c3fb27SDimitry Andric  defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, Ext, GPR, Ext.PrimaryTy,
33506c3fb27SDimitry Andric                                      "fcvt.lu.s", [IsRV64]>,
33606c3fb27SDimitry Andric                    Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
33706c3fb27SDimitry Andric
33806c3fb27SDimitry Andric  defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, Ext, Ext.PrimaryTy, GPR,
33906c3fb27SDimitry Andric                                    "fcvt.s.l", [IsRV64]>,
34006c3fb27SDimitry Andric                  Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
34106c3fb27SDimitry Andric
34206c3fb27SDimitry Andric  defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, Ext, Ext.PrimaryTy, GPR,
34306c3fb27SDimitry Andric                                     "fcvt.s.lu", [IsRV64]>,
34406c3fb27SDimitry Andric                   Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
34506c3fb27SDimitry Andric} // foreach Ext = FExts
3460b57cec5SDimitry Andric
347bdd1243dSDimitry Andriclet Predicates = [HasStdExtF], mayRaiseFPException = 0,
348bdd1243dSDimitry Andric    IsSignExtendingOpW = 1 in
3490eae32dcSDimitry Andricdef FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,
3500eae32dcSDimitry Andric              Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;
3510eae32dcSDimitry Andric
352bdd1243dSDimitry Andriclet Predicates = [HasStdExtF], mayRaiseFPException = 0 in
3530eae32dcSDimitry Andricdef FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,
3540eae32dcSDimitry Andric              Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
3570b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
3580b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
3610b57cec5SDimitry Andricdef : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;
3620b57cec5SDimitry Andricdef : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andricdef : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
3650b57cec5SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
3660b57cec5SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric// fgt.s/fge.s are recognised by the GNU assembler but the canonical
3690b57cec5SDimitry Andric// flt.s/fle.s forms will always be printed. Therefore, set a zero weight.
3700b57cec5SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt",
3710b57cec5SDimitry Andric                (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
3720b57cec5SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt",
3730b57cec5SDimitry Andric                (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
3740b57cec5SDimitry Andric
3750b57cec5SDimitry Andric// The following csr instructions actually alias instructions from the base ISA.
3760b57cec5SDimitry Andric// However, it only makes sense to support them when the F extension is enabled.
3770b57cec5SDimitry Andric// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr".
378fe6060f1SDimitry Andricdef : InstAlias<"frcsr $rd",      (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>;
379fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>;
380fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rs",      (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 2>;
3810b57cec5SDimitry Andric
3828bcb0991SDimitry Andric// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them
3838bcb0991SDimitry Andric// zero weight.
384fe6060f1SDimitry Andricdef : InstAlias<"frsr $rd",       (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>;
385fe6060f1SDimitry Andricdef : InstAlias<"fssr $rd, $rs",  (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>;
386fe6060f1SDimitry Andricdef : InstAlias<"fssr $rs",       (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 0>;
3878bcb0991SDimitry Andric
388fe6060f1SDimitry Andricdef : InstAlias<"frrm $rd",        (CSRRS  GPR:$rd, SysRegFRM.Encoding, X0), 2>;
389fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rd, $rs",   (CSRRW  GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>;
390fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rs",        (CSRRW       X0, SysRegFRM.Encoding, GPR:$rs), 2>;
391fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>;
392fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $imm",      (CSRRWI      X0, SysRegFRM.Encoding, uimm5:$imm), 2>;
3930b57cec5SDimitry Andric
394fe6060f1SDimitry Andricdef : InstAlias<"frflags $rd",        (CSRRS  GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>;
395fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rd, $rs",   (CSRRW  GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>;
396fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rs",        (CSRRW       X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>;
397fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>;
398fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>;
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both
4010b57cec5SDimitry Andric// spellings should be supported by standard tools.
4020b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.s.x", "fmv.w.x">;
4030b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.x.s", "fmv.x.w">;
4040b57cec5SDimitry Andric
4050b57cec5SDimitry Andricdef PseudoFLW  : PseudoFloatLoad<"flw", FPR32>;
4060b57cec5SDimitry Andricdef PseudoFSW  : PseudoStore<"fsw", FPR32>;
40704eeddc0SDimitry Andriclet usesCustomInserter = 1 in {
40804eeddc0SDimitry Andricdef PseudoQuietFLE_S : PseudoQuietFCMP<FPR32>;
40904eeddc0SDimitry Andricdef PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>;
41004eeddc0SDimitry Andric}
4110b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
4120b57cec5SDimitry Andric
413d56accc7SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
414d56accc7SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
415d56accc7SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
416d56accc7SDimitry Andric
417d56accc7SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt",
418d56accc7SDimitry Andric                (FLT_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
419d56accc7SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt",
420d56accc7SDimitry Andric                (FLE_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
42106c3fb27SDimitry Andriclet usesCustomInserter = 1 in {
42206c3fb27SDimitry Andricdef PseudoQuietFLE_S_INX : PseudoQuietFCMP<FPR32INX>;
42306c3fb27SDimitry Andricdef PseudoQuietFLT_S_INX : PseudoQuietFCMP<FPR32INX>;
42406c3fb27SDimitry Andric}
425d56accc7SDimitry Andric} // Predicates = [HasStdExtZfinx]
426d56accc7SDimitry Andric
4270b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4280b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
4290b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4300b57cec5SDimitry Andric
43106c3fb27SDimitry Andricdefvar FRM_RNE = 0b000;
43206c3fb27SDimitry Andricdefvar FRM_RTZ = 0b001;
43306c3fb27SDimitry Andricdefvar FRM_RDN = 0b010;
43406c3fb27SDimitry Andricdefvar FRM_RUP = 0b011;
43506c3fb27SDimitry Andricdefvar FRM_RMM = 0b100;
43606c3fb27SDimitry Andricdefvar FRM_DYN = 0b111;
43706c3fb27SDimitry Andric
4385ffd83dbSDimitry Andric/// Floating point constants
4395ffd83dbSDimitry Andricdef fpimm0    : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
4405ffd83dbSDimitry Andric
4410b57cec5SDimitry Andric/// Generic pattern classes
44206c3fb27SDimitry Andricclass PatSetCC<DAGOperand Ty, SDPatternOperator OpNode, CondCode Cond,
44306c3fb27SDimitry Andric               RVInst Inst, ValueType vt>
44406c3fb27SDimitry Andric    : Pat<(XLenVT (OpNode (vt Ty:$rs1), Ty:$rs2, Cond)), (Inst $rs1, $rs2)>;
44506c3fb27SDimitry Andricmulticlass PatSetCC_m<SDPatternOperator OpNode, CondCode Cond,
44606c3fb27SDimitry Andric                      RVInst Inst, ExtInfo Ext, ValueType vt> {
44706c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
44806c3fb27SDimitry Andric  def Ext.Suffix : PatSetCC<Ext.PrimaryTy, OpNode, Cond,
44906c3fb27SDimitry Andric                            !cast<RVInst>(Inst#Ext.Suffix), vt>;
45006c3fb27SDimitry Andric}
45104eeddc0SDimitry Andric
45281ad6265SDimitry Andricclass PatFprFpr<SDPatternOperator OpNode, RVInstR Inst,
45306c3fb27SDimitry Andric                DAGOperand RegTy, ValueType vt>
45406c3fb27SDimitry Andric    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2)>;
45506c3fb27SDimitry Andricmulticlass PatFprFpr_m<SDPatternOperator OpNode, RVInstR Inst,
45606c3fb27SDimitry Andric                       ExtInfo Ext> {
45706c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
45806c3fb27SDimitry Andric  def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),
45906c3fb27SDimitry Andric                             Ext.PrimaryTy, Ext.PrimaryVT>;
46006c3fb27SDimitry Andric}
4610b57cec5SDimitry Andric
46281ad6265SDimitry Andricclass PatFprFprDynFrm<SDPatternOperator OpNode, RVInstRFrm Inst,
46306c3fb27SDimitry Andric                      DAGOperand RegTy, ValueType vt>
46406c3fb27SDimitry Andric    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2, FRM_DYN)>;
46506c3fb27SDimitry Andricmulticlass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,
46606c3fb27SDimitry Andric                             ExtInfo Ext> {
46706c3fb27SDimitry Andric  let Predicates = Ext.Predicates in
46806c3fb27SDimitry Andric  def Ext.Suffix : PatFprFprDynFrm<OpNode,
46906c3fb27SDimitry Andric                                   !cast<RVInstRFrm>(Inst#Ext.Suffix),
47006c3fb27SDimitry Andric                                   Ext.PrimaryTy, Ext.PrimaryVT>;
47106c3fb27SDimitry Andric}
4725ffd83dbSDimitry Andric
4730b57cec5SDimitry Andric/// Float conversion operations
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so
4760b57cec5SDimitry Andric// are defined later.
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric/// Float arithmetic operations
47906c3fb27SDimitry Andricforeach Ext = FExts in {
48006c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fadd, FADD_S, Ext>;
48106c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, Ext>;
48206c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, Ext>;
48306c3fb27SDimitry Andric  defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, Ext>;
48406c3fb27SDimitry Andric}
4850b57cec5SDimitry Andric
48606c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
48706c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andricdef : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;
4900b57cec5SDimitry Andricdef : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;
4910b57cec5SDimitry Andric
49206c3fb27SDimitry Andricdef : Pat<(riscv_fpclass FPR32:$rs1), (FCLASS_S $rs1)>;
49306c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
49406c3fb27SDimitry Andric
49506c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
49606c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR32INX:$rs1), (FSQRT_S_INX FPR32INX:$rs1, FRM_DYN)>;
49706c3fb27SDimitry Andric
49806c3fb27SDimitry Andricdef : Pat<(fneg FPR32INX:$rs1), (FSGNJN_S_INX $rs1, $rs1)>;
49906c3fb27SDimitry Andricdef : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>;
50006c3fb27SDimitry Andric
50106c3fb27SDimitry Andricdef : Pat<(riscv_fpclass FPR32INX:$rs1), (FCLASS_S_INX $rs1)>;
50206c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
50306c3fb27SDimitry Andric
50406c3fb27SDimitry Andricforeach Ext = FExts in
50506c3fb27SDimitry Andricdefm : PatFprFpr_m<fcopysign, FSGNJ_S, Ext>;
50606c3fb27SDimitry Andric
50706c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
5080b57cec5SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;
5090b57cec5SDimitry Andric
5100b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3
5110eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3),
51206c3fb27SDimitry Andric          (FMADD_S $rs1, $rs2, $rs3, FRM_DYN)>;
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3
5150eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)),
51606c3fb27SDimitry Andric          (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3
5190eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3),
52006c3fb27SDimitry Andric          (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3
5230eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)),
52406c3fb27SDimitry Andric          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
5250b57cec5SDimitry Andric
52681ad6265SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
52781ad6265SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR32:$rs1, FPR32:$rs2, FPR32:$rs3)),
52806c3fb27SDimitry Andric          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
52906c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
53006c3fb27SDimitry Andric
53106c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
53206c3fb27SDimitry Andricdef : Pat<(fcopysign FPR32INX:$rs1, (fneg FPR32INX:$rs2)), (FSGNJN_S_INX $rs1, $rs2)>;
53306c3fb27SDimitry Andric
53406c3fb27SDimitry Andric// fmadd: rs1 * rs2 + rs3
53506c3fb27SDimitry Andricdef : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3),
53606c3fb27SDimitry Andric          (FMADD_S_INX $rs1, $rs2, $rs3, FRM_DYN)>;
53706c3fb27SDimitry Andric
53806c3fb27SDimitry Andric// fmsub: rs1 * rs2 - rs3
53906c3fb27SDimitry Andricdef : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
54006c3fb27SDimitry Andric          (FMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
54106c3fb27SDimitry Andric
54206c3fb27SDimitry Andric// fnmsub: -rs1 * rs2 + rs3
54306c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, FPR32INX:$rs3),
54406c3fb27SDimitry Andric          (FNMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
54506c3fb27SDimitry Andric
54606c3fb27SDimitry Andric// fnmadd: -rs1 * rs2 - rs3
54706c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
54806c3fb27SDimitry Andric          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
54906c3fb27SDimitry Andric
55006c3fb27SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
55106c3fb27SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3)),
55206c3fb27SDimitry Andric          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
55306c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
55481ad6265SDimitry Andric
555fe6060f1SDimitry Andric// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
556fe6060f1SDimitry Andric// LLVM's fminnum and fmaxnum
5570b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
55806c3fb27SDimitry Andricforeach Ext = FExts in {
55906c3fb27SDimitry Andric  defm : PatFprFpr_m<fminnum, FMIN_S, Ext>;
56006c3fb27SDimitry Andric  defm : PatFprFpr_m<fmaxnum, FMAX_S, Ext>;
56106c3fb27SDimitry Andric  defm : PatFprFpr_m<riscv_fmin, FMIN_S, Ext>;
56206c3fb27SDimitry Andric  defm : PatFprFpr_m<riscv_fmax, FMAX_S, Ext>;
56306c3fb27SDimitry Andric}
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andric/// Setcc
56604eeddc0SDimitry Andric// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
56704eeddc0SDimitry Andric// strict versions of those.
5680b57cec5SDimitry Andric
56904eeddc0SDimitry Andric// Match non-signaling FEQ_S
57006c3fb27SDimitry Andricforeach Ext = FExts in {
57106c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            Ext, f32>;
57206c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            Ext, f32>;
57306c3fb27SDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, Ext, f32>;
57406c3fb27SDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, Ext, f32>;
57506c3fb27SDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, Ext, f32>;
57606c3fb27SDimitry Andric  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, Ext, f32>;
57706c3fb27SDimitry Andric}
57804eeddc0SDimitry Andric
57906c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
58004eeddc0SDimitry Andric// Match signaling FEQ_S
58106c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETEQ)),
58204eeddc0SDimitry Andric          (AND (FLE_S $rs1, $rs2),
58304eeddc0SDimitry Andric               (FLE_S $rs2, $rs1))>;
58406c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETOEQ)),
58504eeddc0SDimitry Andric          (AND (FLE_S $rs1, $rs2),
58604eeddc0SDimitry Andric               (FLE_S $rs2, $rs1))>;
58704eeddc0SDimitry Andric// If both operands are the same, use a single FLE.
58806c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETEQ)),
58904eeddc0SDimitry Andric          (FLE_S $rs1, $rs1)>;
59006c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETOEQ)),
59104eeddc0SDimitry Andric          (FLE_S $rs1, $rs1)>;
59206c3fb27SDimitry Andric} // Predicates = [HasStdExtF]
59304eeddc0SDimitry Andric
59406c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
59506c3fb27SDimitry Andric// Match signaling FEQ_S
59606c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETEQ)),
59706c3fb27SDimitry Andric          (AND (FLE_S_INX $rs1, $rs2),
59806c3fb27SDimitry Andric               (FLE_S_INX $rs2, $rs1))>;
59906c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETOEQ)),
60006c3fb27SDimitry Andric          (AND (FLE_S_INX $rs1, $rs2),
60106c3fb27SDimitry Andric               (FLE_S_INX $rs2, $rs1))>;
60206c3fb27SDimitry Andric// If both operands are the same, use a single FLE.
60306c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETEQ)),
60406c3fb27SDimitry Andric          (FLE_S_INX $rs1, $rs1)>;
60506c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETOEQ)),
60606c3fb27SDimitry Andric          (FLE_S_INX $rs1, $rs1)>;
60706c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
6080b57cec5SDimitry Andric
60906c3fb27SDimitry Andricforeach Ext = FExts in {
61006c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, Ext, f32>;
61106c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, Ext, f32>;
61206c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, Ext, f32>;
61306c3fb27SDimitry Andric  defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, Ext, f32>;
61406c3fb27SDimitry Andric}
615bdd1243dSDimitry Andric
61606c3fb27SDimitry Andriclet Predicates = [HasStdExtF] in {
61706c3fb27SDimitry Andricdefm Select_FPR32 : SelectCC_GPR_rrirr<FPR32, f32>;
61806c3fb27SDimitry Andric
61906c3fb27SDimitry Andricdef PseudoFROUND_S : PseudoFROUND<FPR32, f32>;
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric/// Loads
6220b57cec5SDimitry Andric
62306c3fb27SDimitry Andricdef : LdPat<load, FLW, f32>;
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric/// Stores
6260b57cec5SDimitry Andric
62706c3fb27SDimitry Andricdef : StPat<store, FSW, FPR32, f32>;
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
6300b57cec5SDimitry Andric
63106c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx] in {
63206c3fb27SDimitry Andricdefm Select_FPR32INX : SelectCC_GPR_rrirr<FPR32INX, f32>;
63306c3fb27SDimitry Andric
63406c3fb27SDimitry Andricdef PseudoFROUND_S_INX : PseudoFROUND<FPR32INX, f32>;
63506c3fb27SDimitry Andric
63606c3fb27SDimitry Andric/// Loads
63706c3fb27SDimitry Andricdef : Pat<(f32 (load (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))),
63806c3fb27SDimitry Andric          (COPY_TO_REGCLASS (LW GPR:$rs1, simm12:$imm12), GPRF32)>;
63906c3fb27SDimitry Andric
64006c3fb27SDimitry Andric/// Stores
64106c3fb27SDimitry Andricdef : Pat<(store (f32 FPR32INX:$rs2), (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12)),
64206c3fb27SDimitry Andric          (SW (COPY_TO_REGCLASS FPR32INX:$rs2, GPR), GPR:$rs1, simm12:$imm12)>;
64306c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx]
64406c3fb27SDimitry Andric
6450b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV32] in {
646e8d8bef9SDimitry Andric// Moves (no conversion)
647fe6060f1SDimitry Andricdef : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>;
648fe6060f1SDimitry Andricdef : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>;
64906c3fb27SDimitry Andric} // Predicates = [HasStdExtF, IsRV32]
650e8d8bef9SDimitry Andric
65106c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx, IsRV32] in {
65206c3fb27SDimitry Andric// Moves (no conversion)
65306c3fb27SDimitry Andricdef : Pat<(f32 (bitconvert (i32 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPRF32)>;
65406c3fb27SDimitry Andricdef : Pat<(i32 (bitconvert FPR32INX:$rs1)), (COPY_TO_REGCLASS FPR32INX:$rs1, GPR)>;
65506c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx, IsRV32]
65606c3fb27SDimitry Andric
65706c3fb27SDimitry Andriclet Predicates = [HasStdExtF, IsRV32] in {
6580b57cec5SDimitry Andric// float->[u]int. Round-to-zero must be used.
65906c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RTZ)>;
66006c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, FRM_RTZ)>;
661fe6060f1SDimitry Andric
662349cc55cSDimitry Andric// Saturating float->[u]int32.
66304eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_W_S $rs1, timm:$frm)>;
66404eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_WU_S $rs1, timm:$frm)>;
665349cc55cSDimitry Andric
666fe6060f1SDimitry Andric// float->int32 with current rounding mode.
66706c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_DYN)>;
668fe6060f1SDimitry Andric
669fe6060f1SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero.
67006c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RMM)>;
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode.
67306c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, FRM_DYN)>;
67406c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, FRM_DYN)>;
6750b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV32]
6760b57cec5SDimitry Andric
67706c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx, IsRV32] in {
67806c3fb27SDimitry Andric// float->[u]int. Round-to-zero must be used.
67906c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RTZ)>;
68006c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_WU_S_INX $rs1, FRM_RTZ)>;
68106c3fb27SDimitry Andric
68206c3fb27SDimitry Andric// Saturating float->[u]int32.
68306c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_W_S_INX $rs1, timm:$frm)>;
68406c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_WU_S_INX $rs1, timm:$frm)>;
68506c3fb27SDimitry Andric
68606c3fb27SDimitry Andric// float->int32 with current rounding mode.
68706c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_DYN)>;
68806c3fb27SDimitry Andric
68906c3fb27SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero.
69006c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RMM)>;
69106c3fb27SDimitry Andric
69206c3fb27SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode.
69306c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W_INX $rs1, FRM_DYN)>;
69406c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
69506c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx, IsRV32]
69606c3fb27SDimitry Andric
6970b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in {
698e8d8bef9SDimitry Andric// Moves (no conversion)
6990b57cec5SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>;
7000b57cec5SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;
7010b57cec5SDimitry Andric
702fe6060f1SDimitry Andric// Use target specific isd nodes to help us remember the result is sign
703fe6060f1SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
704fe6060f1SDimitry Andric// duplicated if it has another user that didn't need the sign_extend.
70504eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR32:$rs1, timm:$frm),  (FCVT_W_S $rs1, timm:$frm)>;
70604eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR32:$rs1, timm:$frm), (FCVT_WU_S $rs1, timm:$frm)>;
7070b57cec5SDimitry Andric
708fe6060f1SDimitry Andric// float->[u]int64. Round-to-zero must be used.
70906c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RTZ)>;
71006c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, FRM_RTZ)>;
711fe6060f1SDimitry Andric
712349cc55cSDimitry Andric// Saturating float->[u]int64.
71304eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_L_S $rs1, timm:$frm)>;
71404eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_LU_S $rs1, timm:$frm)>;
715349cc55cSDimitry Andric
716fe6060f1SDimitry Andric// float->int64 with current rounding mode.
71706c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
71806c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
719fe6060f1SDimitry Andric
720fe6060f1SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero.
72106c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
72206c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
7230b57cec5SDimitry Andric
7240b57cec5SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode.
72506c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, FRM_DYN)>;
72606c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, FRM_DYN)>;
72706c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, FRM_DYN)>;
72806c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, FRM_DYN)>;
7290b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64]
73006c3fb27SDimitry Andric
73106c3fb27SDimitry Andriclet Predicates = [HasStdExtZfinx, IsRV64] in {
73206c3fb27SDimitry Andric// Moves (no conversion)
73306c3fb27SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (COPY_TO_REGCLASS GPR:$src, GPRF32)>;
73406c3fb27SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 GPRF32:$src), (COPY_TO_REGCLASS GPRF32:$src, GPR)>;
73506c3fb27SDimitry Andric
73606c3fb27SDimitry Andric// Use target specific isd nodes to help us remember the result is sign
73706c3fb27SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
73806c3fb27SDimitry Andric// duplicated if it has another user that didn't need the sign_extend.
73906c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR32INX:$rs1, timm:$frm),  (FCVT_W_S_INX $rs1, timm:$frm)>;
74006c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR32INX:$rs1, timm:$frm), (FCVT_WU_S_INX $rs1, timm:$frm)>;
74106c3fb27SDimitry Andric
74206c3fb27SDimitry Andric// float->[u]int64. Round-to-zero must be used.
74306c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RTZ)>;
74406c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_LU_S_INX $rs1, FRM_RTZ)>;
74506c3fb27SDimitry Andric
74606c3fb27SDimitry Andric// Saturating float->[u]int64.
74706c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_L_S_INX $rs1, timm:$frm)>;
74806c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_LU_S_INX $rs1, timm:$frm)>;
74906c3fb27SDimitry Andric
75006c3fb27SDimitry Andric// float->int64 with current rounding mode.
75106c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
75206c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
75306c3fb27SDimitry Andric
75406c3fb27SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero.
75506c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
75606c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
75706c3fb27SDimitry Andric
75806c3fb27SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode.
75906c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W_INX $rs1, FRM_DYN)>;
76006c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
76106c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L_INX $rs1, FRM_DYN)>;
76206c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU_INX $rs1, FRM_DYN)>;
76306c3fb27SDimitry Andric} // Predicates = [HasStdExtZfinx, IsRV64]
764