brintos

brintos / llvm-project-archived public Read only

0
0
Text · 37.2 KiB · bd19100 Raw
863 lines · plain
1//===-- RISCVInstrInfoF.td - RISC-V 'F' instructions -------*- tablegen -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file describes the RISC-V instructions from the standard 'F',10// Single-Precision Floating-Point instruction set extension.11//12//===----------------------------------------------------------------------===//13 14//===----------------------------------------------------------------------===//15// RISC-V specific DAG Nodes.16//===----------------------------------------------------------------------===//17 18def SDT_RISCVFMV_W_X_RV6419    : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;20def SDT_RISCVFMV_X_ANYEXTW_RV6421    : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;22def SDT_RISCVFCVT_W_RV6423    : SDTypeProfile<1, 2, [SDTCisVT<0, i64>, SDTCisFP<1>,24                           SDTCisVT<2, i64>]>;25def SDT_RISCVFCVT_X26    : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>, SDTCisFP<1>,27                           SDTCisVT<2, XLenVT>]>;28 29def SDT_RISCVFROUND30    : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,31                           SDTCisVT<3, XLenVT>]>;32def SDT_RISCVFCLASS33    : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>;34def SDT_RISCVFSGNJX35    : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]>;36 37def riscv_fclass38    : RVSDNode<"FCLASS", SDT_RISCVFCLASS>;39 40// Rounds an FP value to its corresponding integer in the same FP format.41// First operand is the value to round, the second operand is the largest42// integer that can be represented exactly in the FP format. This will be43// expanded into multiple instructions and basic blocks with a custom44// inserter.45def riscv_fround46    : RVSDNode<"FROUND", SDT_RISCVFROUND>;47 48def riscv_fsgnjx49    : RVSDNode<"FSGNJX", SDT_RISCVFSGNJX>;50 51// FPR<->GPR transfer operations when the FPR is smaller than XLEN, needed as52// XLEN is the only legal integer width.53//54// FMV_W_X_RV64 matches the semantics of the FMV.W.X.55// FMV_X_ANYEXTW_RV64 is similar to FMV.X.W but has an any-extended result.56//57// This is a more convenient semantic for producing dagcombines that remove58// unnecessary GPR->FPR->GPR moves.59def riscv_fmv_w_x_rv6460    : RVSDNode<"FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>;61def riscv_fmv_x_anyextw_rv6462    : RVSDNode<"FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>;63 64// FP to 32 bit int conversions for RV64. These are used to keep track of the65// result being sign extended to 64 bit. These saturate out of range inputs.66// Used for FP_TO_S/UINT and FP_TO_S/UINT_SAT lowering. Rounding mode67// is passed as a TargetConstant operand using the RISCVFPRndMode enum.68def riscv_fcvt_w_rv6469    : RVSDNode<"FCVT_W_RV64", SDT_RISCVFCVT_W_RV64>;70def riscv_fcvt_wu_rv6471    : RVSDNode<"FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64>;72 73// FP to XLen int conversions. Corresponds to fcvt.l(u).s/d/h on RV64 and74// fcvt.w(u).s/d/h on RV32. Unlike FP_TO_S/UINT these saturate out of75// range inputs. These are used for FP_TO_S/UINT_SAT lowering. Rounding mode76// is passed as a TargetConstant operand using the RISCVFPRndMode enum.77def riscv_fcvt_x78    : RVSDNode<"FCVT_X", SDT_RISCVFCVT_X>;79def riscv_fcvt_xu80    : RVSDNode<"FCVT_XU", SDT_RISCVFCVT_X>;81 82// Floating point fmax and fmin matching the RISC-V instruction semantics.83def riscv_fmin : RVSDNode<"FMIN", SDTFPBinOp>;84def riscv_fmax : RVSDNode<"FMAX", SDTFPBinOp>;85 86let IsStrictFP = true in {87  // FP to 32 bit int conversions for RV64. These are used to keep track of the88  // result being sign extended to 64 bit. These saturate out of range inputs.89  def riscv_strict_fcvt_w_rv6490      : RVSDNode<"STRICT_FCVT_W_RV64", SDT_RISCVFCVT_W_RV64,91              [SDNPHasChain]>;92  def riscv_strict_fcvt_wu_rv6493      : RVSDNode<"STRICT_FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64,94              [SDNPHasChain]>;95}96 97def riscv_any_fcvt_w_rv64 : PatFrags<(ops node:$src, node:$frm),98                                     [(riscv_strict_fcvt_w_rv64 node:$src, node:$frm),99                                      (riscv_fcvt_w_rv64 node:$src, node:$frm)]>;100def riscv_any_fcvt_wu_rv64 : PatFrags<(ops node:$src, node:$frm),101                                      [(riscv_strict_fcvt_wu_rv64 node:$src, node:$frm),102                                       (riscv_fcvt_wu_rv64 node:$src, node:$frm)]>;103 104def any_fma_nsz : PatFrag<(ops node:$rs1, node:$rs2, node:$rs3),105                          (any_fma node:$rs1, node:$rs2, node:$rs3), [{106  return N->getFlags().hasNoSignedZeros();107}]>;108//===----------------------------------------------------------------------===//109// Operand and SDNode transformation definitions.110//===----------------------------------------------------------------------===//111 112// Zfinx113 114def GPRAsFPR32 : AsmOperandClass {115  let Name = "GPRAsFPR32";116  let ParserMethod = "parseGPRAsFPR";117  let RenderMethod = "addRegOperands";118}119 120def FPR32INX : RegisterOperand<GPRF32> {121  let ParserMatchClass = GPRAsFPR32;122}123 124// Describes a combination of predicates from F/D/Q/Zfh/Zfhmin or125// Zfinx/Zdinx/Zhinx/Zhinxmin that are applied to scalar FP instruction.126// Contains the DAGOperand for the primary type for the predicates. The primary127// type may be unset for combinations of predicates like Zfh+D.128// Also contains the DAGOperand for f16/f32/f64, instruction suffix, and129// decoder namespace that go with an instruction given those predicates.130//131// The DAGOperand can be unset if the predicates are not enough to define it.132class ExtInfo<string suffix, string space, list<Predicate> predicates,133              ValueType primaryvt, DAGOperand primaryty, DAGOperand f32ty,134              DAGOperand f64ty, DAGOperand f16ty, ValueType intvt = XLenVT> {135  list<Predicate> Predicates = predicates;136  string Suffix = suffix;137  string Space = space;138  DAGOperand PrimaryTy = primaryty;139  DAGOperand F16Ty = f16ty;140  DAGOperand F32Ty = f32ty;141  DAGOperand F64Ty = f64ty;142  ValueType PrimaryVT = primaryvt;143  ValueType IntVT = intvt;144}145 146def FExt       : ExtInfo<"", "", [HasStdExtF], f32, FPR32, FPR32, ?, ?>;147 148def ZfinxExt   : ExtInfo<"_INX", "Zfinx", [HasStdExtZfinx], f32, FPR32INX, FPR32INX, ?, ?>;149 150defvar FExts   = [FExt, ZfinxExt];151 152// Floating-point rounding mode153 154def FRMArg : AsmOperandClass {155  let Name = "FRMArg";156  let RenderMethod = "addFRMArgOperands";157  let ParserMethod = "parseFRMArg";158  let IsOptional = 1;159  let DefaultMethod = "defaultFRMArgOp";160}161 162def frmarg : Operand<XLenVT> {163  let ParserMatchClass = FRMArg;164  let PrintMethod = "printFRMArg";165  let DecoderMethod = "decodeFRMArg";166  let OperandType = "OPERAND_FRMARG";167  let OperandNamespace = "RISCVOp";168}169 170// Variants of the rounding mode operand that default to 'rne'. This is used171// for historical/legacy reasons. fcvt functions where the rounding mode172// doesn't affect the output originally always set it to 0b000 ('rne'). As old173// versions of LLVM and GCC will fail to decode versions of these instructions174// with the rounding mode set to something other than 'rne', we retain this175// default.176def FRMArgLegacy : AsmOperandClass {177  let Name = "FRMArgLegacy";178  let RenderMethod = "addFRMArgOperands";179  let ParserMethod = "parseFRMArg";180  let IsOptional = 1;181  let DefaultMethod = "defaultFRMArgLegacyOp";182}183 184def frmarglegacy : Operand<XLenVT> {185  let ParserMatchClass = FRMArgLegacy;186  let PrintMethod = "printFRMArgLegacy";187  let DecoderMethod = "decodeFRMArg";188  let OperandType = "OPERAND_FRMARG";189  let OperandNamespace = "RISCVOp";190}191 192//===----------------------------------------------------------------------===//193// Instruction class templates194//===----------------------------------------------------------------------===//195 196let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in197class FPLoad_r<bits<3> funct3, string opcodestr, DAGOperand rty,198               SchedWrite sw>199    : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd),200              (ins GPRMem:$rs1, simm12_lo:$imm12),201              opcodestr, "$rd, ${imm12}(${rs1})">,202      Sched<[sw, ReadFMemBase]>;203 204let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in205class FPStore_r<bits<3> funct3, string opcodestr, DAGOperand rty,206                SchedWrite sw>207    : RVInstS<funct3, OPC_STORE_FP, (outs),208              (ins rty:$rs2, GPRMem:$rs1, simm12_lo:$imm12),209              opcodestr, "$rs2, ${imm12}(${rs1})">,210      Sched<[sw, ReadFStoreData, ReadFMemBase]>;211 212let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,213    UseNamedOperandTable = 1, hasPostISelHook = 1, isCommutable = 1 in214class FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,215                    DAGOperand rty>216    : RVInstR4Frm<funct2, opcode, (outs rty:$rd),217                  (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm),218                  opcodestr, "$rd, $rs1, $rs2, $rs3$frm">;219 220multiclass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,221                           string opcodestr, ExtInfo Ext> {222  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in223  def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.PrimaryTy>;224}225 226let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in227class FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,228               DAGOperand rty, bit Commutable>229    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd),230              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {231  let isCommutable = Commutable;232}233multiclass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,234                      ExtInfo Ext, bit Commutable = 0> {235  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in236  def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;237}238 239let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,240    UseNamedOperandTable = 1, hasPostISelHook = 1 in241class FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty,242                   bit Commutable>243    : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd),244                 (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr,245                  "$rd, $rs1, $rs2$frm"> {246  let isCommutable = Commutable;247}248multiclass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,249                          ExtInfo Ext, bit Commutable = 0> {250  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in251  def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.PrimaryTy, Commutable>;252}253 254let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in255class FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,256                  DAGOperand rdty, DAGOperand rs1ty, string opcodestr>257    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),258              opcodestr, "$rd, $rs1"> {259  let rs2 = rs2val;260}261multiclass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,262                         ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,263                         string opcodestr> {264  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in265  def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, rdty, rs1ty, opcodestr>;266}267 268let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,269    UseNamedOperandTable = 1, hasPostISelHook = 1 in270class FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,271                      DAGOperand rs1ty, string opcodestr>272    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),273                 (ins rs1ty:$rs1, frmarg:$frm), opcodestr,274                  "$rd, $rs1$frm"> {275  let rs2 = rs2val;276}277multiclass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,278                             ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,279                             string opcodestr, list<Predicate> ExtraPreds = []> {280  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),281      DecoderNamespace = Ext.Space in282  def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, rdty, rs1ty,283                                   opcodestr>;284}285 286let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,287    UseNamedOperandTable = 1, hasPostISelHook = 1 in288class FPUnaryOp_r_frmlegacy<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,289                            DAGOperand rs1ty, string opcodestr>290    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),291                 (ins rs1ty:$rs1, frmarglegacy:$frm), opcodestr,292                  "$rd, $rs1$frm"> {293  let rs2 = rs2val;294}295multiclass FPUnaryOp_r_frmlegacy_m<bits<7> funct7, bits<5> rs2val,296                                   ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,297                                   string opcodestr, list<Predicate> ExtraPreds = []> {298  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),299      DecoderNamespace = Ext.Space in300  def Ext.Suffix : FPUnaryOp_r_frmlegacy<funct7, rs2val, rdty, rs1ty,301                                         opcodestr>;302}303 304let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,305    IsSignExtendingOpW = 1 in306class FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,307               DAGOperand rty, bit Commutable = 0>308    : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd),309              (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {310  let isCommutable = Commutable;311}312multiclass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,313                      ExtInfo Ext, bit Commutable = 0> {314  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in315  def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;316}317 318class PseudoFROUND<DAGOperand Ty, ValueType vt, ValueType intvt = XLenVT>319    : Pseudo<(outs Ty:$rd), (ins Ty:$rs1, Ty:$rs2, ixlenimm:$rm),320      [(set Ty:$rd, (vt (riscv_fround Ty:$rs1, Ty:$rs2, (intvt timm:$rm))))]> {321  let hasSideEffects = 0;322  let mayLoad = 0;323  let mayStore = 0;324  let usesCustomInserter = 1;325  let mayRaiseFPException = 1;326}327 328//===----------------------------------------------------------------------===//329// Instructions330//===----------------------------------------------------------------------===//331 332let Predicates = [HasStdExtF] in {333let canFoldAsLoad = 1, isReMaterializable = 1 in334def FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;335 336// Operands for stores are in the order srcreg, base, offset rather than337// reflecting the order these fields are specified in the instruction338// encoding.339def FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;340} // Predicates = [HasStdExtF]341 342let Predicates = [HasStdExtZfinx], isCodeGenOnly = 1 in {343def LW_INX : Load_ri<0b010, "lw", GPRF32>, Sched<[WriteLDW, ReadMemBase]>;344def SW_INX : Store_rri<0b010, "sw", GPRF32>,345             Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;346 347// ADDI with GPRF32 register class to use for copy. This should not be used as348// general ADDI, so the immediate should always be zero.349let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveReg = 1,350    hasSideEffects = 0, mayLoad = 0, mayStore = 0 in351def PseudoMV_FPR32INX : Pseudo<(outs GPRF32:$rd), (ins GPRF32:$rs), []>,352                        Sched<[WriteIALU, ReadIALU]>;353}354 355foreach Ext = FExts in {356  let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32Addend] in {357    defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  Ext>;358    defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  Ext>;359    defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", Ext>;360    defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", Ext>;361  }362 363  let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {364    defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, Commutable=1>;365    defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>;366  }367 368  let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in369  defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, Commutable=1>;370 371  let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in372  defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>;373 374  defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, Ext, Ext.PrimaryTy,375                                   Ext.PrimaryTy, "fsqrt.s">,376                 Sched<[WriteFSqrt32, ReadFSqrt32]>;377 378  let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],379      mayRaiseFPException = 0 in {380    defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  Ext>;381    defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", Ext>;382    defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", Ext>;383  }384 385  let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {386    defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, Commutable=1>;387    defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, Commutable=1>;388  }389 390  let IsSignExtendingOpW = 1 in391  defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, Ext, GPR, Ext.PrimaryTy,392                                    "fcvt.w.s">,393                  Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;394 395  let IsSignExtendingOpW = 1 in396  defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, Ext, GPR, Ext.PrimaryTy,397                                     "fcvt.wu.s">,398                   Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;399 400  let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {401  defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, Commutable=1>;402  defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>;403  defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>;404  }405 406  let mayRaiseFPException = 0 in407  defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,408                                "fclass.s">,409                  Sched<[WriteFClass32, ReadFClass32]>;410 411  defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, Ext, Ext.PrimaryTy, GPR,412                                    "fcvt.s.w">,413                  Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;414 415  defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, Ext, Ext.PrimaryTy, GPR,416                                     "fcvt.s.wu">,417                   Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;418 419  defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, Ext, GPR, Ext.PrimaryTy,420                                     "fcvt.l.s", [IsRV64]>,421                   Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;422 423  defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, Ext, GPR, Ext.PrimaryTy,424                                      "fcvt.lu.s", [IsRV64]>,425                    Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;426 427  defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, Ext, Ext.PrimaryTy, GPR,428                                    "fcvt.s.l", [IsRV64]>,429                  Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;430 431  defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, Ext, Ext.PrimaryTy, GPR,432                                     "fcvt.s.lu", [IsRV64]>,433                   Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;434} // foreach Ext = FExts435 436let Predicates = [HasStdExtF], mayRaiseFPException = 0,437    IsSignExtendingOpW = 1 in438def FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,439              Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;440 441let Predicates = [HasStdExtF], mayRaiseFPException = 0 in442def FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,443              Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;444 445//===----------------------------------------------------------------------===//446// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)447//===----------------------------------------------------------------------===//448 449let Predicates = [HasStdExtFOrZfinx] in {450// The following csr instructions actually alias instructions from the base ISA.451// However, it only makes sense to support them when the F or Zfinx extension is452// enabled.453// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr".454def : InstAlias<"frcsr $rd",      (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>;455def : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>;456def : InstAlias<"fscsr $rs",      (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 2>;457 458// frsr, fssr are obsolete aliases replaced by frcsr, fscsr.459def : MnemonicAlias<"frsr", "frcsr">;460def : MnemonicAlias<"fssr", "fscsr">;461 462def : InstAlias<"frrm $rd",        (CSRRS  GPR:$rd, SysRegFRM.Encoding, X0), 2>;463def : InstAlias<"fsrm $rd, $rs",   (CSRRW  GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>;464def : InstAlias<"fsrm $rs",        (CSRRW       X0, SysRegFRM.Encoding, GPR:$rs), 2>;465def : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>;466def : InstAlias<"fsrmi $imm",      (CSRRWI      X0, SysRegFRM.Encoding, uimm5:$imm), 2>;467 468def : InstAlias<"frflags $rd",        (CSRRS  GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>;469def : InstAlias<"fsflags $rd, $rs",   (CSRRW  GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>;470def : InstAlias<"fsflags $rs",        (CSRRW       X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>;471def : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>;472def : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>;473} // Predicates = [HasStdExtFOrZfinx]474 475let Predicates = [HasStdExtF] in {476def : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;477def : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;478 479def : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;480def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;481def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;482 483// fgt.s/fge.s are recognised by the GNU assembler but the canonical484// flt.s/fle.s forms will always be printed. Therefore, set a zero weight.485def : InstAlias<"fgt.s $rd, $rs, $rt",486                (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;487def : InstAlias<"fge.s $rd, $rs, $rt",488                (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;489 490// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both491// spellings should be supported by standard tools.492def : MnemonicAlias<"fmv.s.x", "fmv.w.x">;493def : MnemonicAlias<"fmv.x.s", "fmv.x.w">;494 495def PseudoFLW  : PseudoFloatLoad<"flw", FPR32>;496def PseudoFSW  : PseudoStore<"fsw", FPR32>;497let usesCustomInserter = 1 in {498def PseudoQuietFLE_S : PseudoQuietFCMP<FPR32>;499def PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>;500}501} // Predicates = [HasStdExtF]502 503let Predicates = [HasStdExtZfinx] in {504def : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S_INX  FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;505def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;506def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;507 508def : InstAlias<"fgt.s $rd, $rs, $rt",509                (FLT_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;510def : InstAlias<"fge.s $rd, $rs, $rt",511                (FLE_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;512let usesCustomInserter = 1 in {513def PseudoQuietFLE_S_INX : PseudoQuietFCMP<FPR32INX>;514def PseudoQuietFLT_S_INX : PseudoQuietFCMP<FPR32INX>;515}516} // Predicates = [HasStdExtZfinx]517 518//===----------------------------------------------------------------------===//519// Pseudo-instructions and codegen patterns520//===----------------------------------------------------------------------===//521 522defvar FRM_RNE = 0b000;523defvar FRM_RTZ = 0b001;524defvar FRM_RDN = 0b010;525defvar FRM_RUP = 0b011;526defvar FRM_RMM = 0b100;527defvar FRM_DYN = 0b111;528 529/// Floating point constants530def fpimm0    : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;531 532/// Generic pattern classes533class PatSetCC<DAGOperand Ty, SDPatternOperator OpNode, CondCode Cond,534               RVInstCommon Inst, ValueType vt, ValueType intvt = XLenVT>535    : Pat<(intvt (OpNode (vt Ty:$rs1), Ty:$rs2, Cond)), (Inst $rs1, $rs2)>;536multiclass PatSetCC_m<SDPatternOperator OpNode, CondCode Cond,537                      RVInstCommon Inst, ExtInfo Ext> {538  let Predicates = Ext.Predicates in539  def Ext.Suffix : PatSetCC<Ext.PrimaryTy, OpNode, Cond,540                            !cast<RVInstCommon>(Inst#Ext.Suffix),541                            Ext.PrimaryVT, Ext.IntVT>;542}543 544class PatFprFpr<SDPatternOperator OpNode, RVInstR Inst,545                DAGOperand RegTy, ValueType vt>546    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2)>;547multiclass PatFprFpr_m<SDPatternOperator OpNode, RVInstR Inst,548                       ExtInfo Ext> {549  let Predicates = Ext.Predicates in550  def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),551                             Ext.PrimaryTy, Ext.PrimaryVT>;552}553 554class PatFprFprDynFrm<SDPatternOperator OpNode, RVInstRFrm Inst,555                      DAGOperand RegTy, ValueType vt, ValueType intvt>556    : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)),557          (Inst $rs1, $rs2,(intvt FRM_DYN))>;558multiclass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,559                             ExtInfo Ext> {560  let Predicates = Ext.Predicates in561  def Ext.Suffix : PatFprFprDynFrm<OpNode,562                                   !cast<RVInstRFrm>(Inst#Ext.Suffix),563                                   Ext.PrimaryTy, Ext.PrimaryVT, Ext.IntVT>;564}565 566/// Float conversion operations567 568// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so569// are defined later.570 571/// Float arithmetic operations572foreach Ext = FExts in {573  defm : PatFprFprDynFrm_m<any_fadd, FADD_S, Ext>;574  defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, Ext>;575  defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, Ext>;576  defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, Ext>;577}578 579let Predicates = [HasStdExtF] in {580def : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;581 582def : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;583def : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;584 585def : Pat<(riscv_fclass FPR32:$rs1), (FCLASS_S $rs1)>;586} // Predicates = [HasStdExtF]587 588let Predicates = [HasStdExtZfinx] in {589def : Pat<(any_fsqrt FPR32INX:$rs1), (FSQRT_S_INX FPR32INX:$rs1, FRM_DYN)>;590 591def : Pat<(fneg FPR32INX:$rs1), (FSGNJN_S_INX $rs1, $rs1)>;592def : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>;593 594def : Pat<(riscv_fclass FPR32INX:$rs1), (FCLASS_S_INX $rs1)>;595} // Predicates = [HasStdExtZfinx]596 597foreach Ext = FExts in {598defm : PatFprFpr_m<fcopysign, FSGNJ_S, Ext>;599defm : PatFprFpr_m<riscv_fsgnjx, FSGNJX_S, Ext>;600}601 602let Predicates = [HasStdExtF] in {603def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)),604          (FSGNJN_S FPR32:$rs1, FPR32:$rs2)>;605 606// fmadd: rs1 * rs2 + rs3607def : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3),608          (FMADD_S $rs1, $rs2, $rs3, FRM_DYN)>;609 610// fmsub: rs1 * rs2 - rs3611def : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)),612          (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;613 614// fnmsub: -rs1 * rs2 + rs3615def : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3),616          (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;617 618// fnmadd: -rs1 * rs2 - rs3619def : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)),620          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;621 622// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)623def : Pat<(fneg (any_fma_nsz FPR32:$rs1, FPR32:$rs2, FPR32:$rs3)),624          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;625} // Predicates = [HasStdExtF]626 627let Predicates = [HasStdExtZfinx] in {628def : Pat<(fcopysign FPR32INX:$rs1, (fneg FPR32INX:$rs2)),629          (FSGNJN_S_INX FPR32INX:$rs1, FPR32INX:$rs2)>;630 631// fmadd: rs1 * rs2 + rs3632def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3),633          (FMADD_S_INX $rs1, $rs2, $rs3, FRM_DYN)>;634 635// fmsub: rs1 * rs2 - rs3636def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, (fneg FPR32INX:$rs3)),637          (FMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;638 639// fnmsub: -rs1 * rs2 + rs3640def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, FPR32INX:$rs3),641          (FNMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;642 643// fnmadd: -rs1 * rs2 - rs3644def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, (fneg FPR32INX:$rs3)),645          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;646 647// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)648def : Pat<(fneg (any_fma_nsz FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3)),649          (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;650} // Predicates = [HasStdExtZfinx]651 652// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches653// LLVM's fminnum and fmaxnum654// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.655foreach Ext = FExts in {656  defm : PatFprFpr_m<fminnum, FMIN_S, Ext>;657  defm : PatFprFpr_m<fmaxnum, FMAX_S, Ext>;658  defm : PatFprFpr_m<fminimumnum, FMIN_S, Ext>;659  defm : PatFprFpr_m<fmaximumnum, FMAX_S, Ext>;660  defm : PatFprFpr_m<riscv_fmin, FMIN_S, Ext>;661  defm : PatFprFpr_m<riscv_fmax, FMAX_S, Ext>;662  let Predicates = Ext.Predicates in663  def : Pat<(f32 (fcanonicalize FPR32:$rs1)), (FMIN_S $rs1, $rs1)>;664}665 666/// Setcc667// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for668// strict versions of those.669 670// Match non-signaling FEQ_S671foreach Ext = FExts in {672  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            Ext>;673  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            Ext>;674  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, Ext>;675  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, Ext>;676  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, Ext>;677  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, Ext>;678}679 680let Predicates = [HasStdExtF] in {681// Match signaling FEQ_S682def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETEQ)),683          (AND (XLenVT (FLE_S $rs1, $rs2)),684               (XLenVT (FLE_S $rs2, $rs1)))>;685def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETOEQ)),686          (AND (XLenVT (FLE_S $rs1, $rs2)),687               (XLenVT (FLE_S $rs2, $rs1)))>;688// If both operands are the same, use a single FLE.689def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETEQ)),690          (FLE_S $rs1, $rs1)>;691def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETOEQ)),692          (FLE_S $rs1, $rs1)>;693} // Predicates = [HasStdExtF]694 695let Predicates = [HasStdExtZfinx] in {696// Match signaling FEQ_S697def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETEQ)),698          (AND (XLenVT (FLE_S_INX $rs1, $rs2)),699               (XLenVT (FLE_S_INX $rs2, $rs1)))>;700def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETOEQ)),701          (AND (XLenVT (FLE_S_INX $rs1, $rs2)),702               (XLenVT (FLE_S_INX $rs2, $rs1)))>;703// If both operands are the same, use a single FLE.704def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETEQ)),705          (FLE_S_INX $rs1, $rs1)>;706def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETOEQ)),707          (FLE_S_INX $rs1, $rs1)>;708} // Predicates = [HasStdExtZfinx]709 710foreach Ext = FExts in {711  defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, Ext>;712  defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, Ext>;713  defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, Ext>;714  defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, Ext>;715}716 717let Predicates = [HasStdExtF] in {718defm Select_FPR32 : SelectCC_GPR_rrirr<FPR32, f32>;719 720def PseudoFROUND_S : PseudoFROUND<FPR32, f32>;721 722/// Loads723 724def : LdPat<load, FLW, f32>;725 726/// Stores727 728def : StPat<store, FSW, FPR32, f32>;729 730} // Predicates = [HasStdExtF]731 732let Predicates = [HasStdExtZfinx] in {733defm Select_FPR32INX : SelectCC_GPR_rrirr<FPR32INX, f32>;734 735def PseudoFROUND_S_INX : PseudoFROUND<FPR32INX, f32>;736 737/// Loads738def : LdPat<load, LW_INX, f32>;739 740/// Stores741def : StPat<store, SW_INX, GPRF32, f32>;742} // Predicates = [HasStdExtZfinx]743 744let Predicates = [HasStdExtF, IsRV32] in {745// Moves (no conversion)746def : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>;747def : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>;748} // Predicates = [HasStdExtF]749 750let Predicates = [HasStdExtZfinx, IsRV32] in {751// Moves (no conversion)752def : Pat<(f32 (bitconvert (i32 GPR:$rs1))), (EXTRACT_SUBREG GPR:$rs1, sub_32)>;753def : Pat<(i32 (bitconvert FPR32INX:$rs1)), (INSERT_SUBREG (XLenVT (IMPLICIT_DEF)), FPR32INX:$rs1, sub_32)>;754} // Predicates = [HasStdExtZfinx]755 756let Predicates = [HasStdExtF, IsRV32] in {757// float->[u]int. Round-to-zero must be used.758def : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RTZ)>;759def : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, FRM_RTZ)>;760 761// Saturating float->[u]int32.762def : Pat<(i32 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_W_S $rs1, timm:$frm)>;763def : Pat<(i32 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_WU_S $rs1, timm:$frm)>;764 765// float->int32 with current rounding mode.766def : Pat<(i32 (any_lrint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_DYN)>;767 768// float->int32 rounded to nearest with ties rounded away from zero.769def : Pat<(i32 (any_lround FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RMM)>;770 771// [u]int->float. Match GCC and default to using dynamic rounding mode.772def : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, FRM_DYN)>;773def : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, FRM_DYN)>;774} // Predicates = [HasStdExtF, IsRV32]775 776let Predicates = [HasStdExtZfinx, IsRV32] in {777// float->[u]int. Round-to-zero must be used.778def : Pat<(i32 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RTZ)>;779def : Pat<(i32 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_WU_S_INX $rs1, FRM_RTZ)>;780 781// Saturating float->[u]int32.782def : Pat<(i32 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_W_S_INX $rs1, timm:$frm)>;783def : Pat<(i32 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_WU_S_INX $rs1, timm:$frm)>;784 785// float->int32 with current rounding mode.786def : Pat<(i32 (any_lrint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_DYN)>;787 788// float->int32 rounded to nearest with ties rounded away from zero.789def : Pat<(i32 (any_lround FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RMM)>;790 791// [u]int->float. Match GCC and default to using dynamic rounding mode.792def : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W_INX $rs1, FRM_DYN)>;793def : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU_INX $rs1, FRM_DYN)>;794} // Predicates = [HasStdExtZfinx, IsRV32]795 796let Predicates = [HasStdExtF, IsRV64] in {797// Moves (no conversion)798def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>;799def : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;800 801// Use target specific isd nodes to help us remember the result is sign802// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be803// duplicated if it has another user that didn't need the sign_extend.804def : Pat<(riscv_any_fcvt_w_rv64 FPR32:$rs1, timm:$frm),  (FCVT_W_S $rs1, timm:$frm)>;805def : Pat<(riscv_any_fcvt_wu_rv64 FPR32:$rs1, timm:$frm), (FCVT_WU_S $rs1, timm:$frm)>;806 807// float->[u]int64. Round-to-zero must be used.808def : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RTZ)>;809def : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, FRM_RTZ)>;810 811// Saturating float->[u]int64.812def : Pat<(i64 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_L_S $rs1, timm:$frm)>;813def : Pat<(i64 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_LU_S $rs1, timm:$frm)>;814 815// float->int64 with current rounding mode.816def : Pat<(i64 (any_lrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;817def : Pat<(i64 (any_llrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;818 819// float->int64 rounded to neartest with ties rounded away from zero.820def : Pat<(i64 (any_lround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;821def : Pat<(i64 (any_llround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;822 823// [u]int->fp. Match GCC and default to using dynamic rounding mode.824def : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, FRM_DYN)>;825def : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, FRM_DYN)>;826def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, FRM_DYN)>;827def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, FRM_DYN)>;828} // Predicates = [HasStdExtF, IsRV64]829 830let Predicates = [HasStdExtZfinx, IsRV64] in {831// Moves (no conversion)832def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (EXTRACT_SUBREG GPR:$src, sub_32)>;833def : Pat<(riscv_fmv_x_anyextw_rv64 GPRF32:$src), (INSERT_SUBREG (XLenVT (IMPLICIT_DEF)), FPR32INX:$src, sub_32)>;834 835// Use target specific isd nodes to help us remember the result is sign836// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be837// duplicated if it has another user that didn't need the sign_extend.838def : Pat<(riscv_any_fcvt_w_rv64 FPR32INX:$rs1, timm:$frm),  (FCVT_W_S_INX $rs1, timm:$frm)>;839def : Pat<(riscv_any_fcvt_wu_rv64 FPR32INX:$rs1, timm:$frm), (FCVT_WU_S_INX $rs1, timm:$frm)>;840 841// float->[u]int64. Round-to-zero must be used.842def : Pat<(i64 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RTZ)>;843def : Pat<(i64 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_LU_S_INX $rs1, FRM_RTZ)>;844 845// Saturating float->[u]int64.846def : Pat<(i64 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_L_S_INX $rs1, timm:$frm)>;847def : Pat<(i64 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_LU_S_INX $rs1, timm:$frm)>;848 849// float->int64 with current rounding mode.850def : Pat<(i64 (any_lrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;851def : Pat<(i64 (any_llrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;852 853// float->int64 rounded to neartest with ties rounded away from zero.854def : Pat<(i64 (any_lround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RMM)>;855def : Pat<(i64 (any_llround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RMM)>;856 857// [u]int->fp. Match GCC and default to using dynamic rounding mode.858def : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W_INX $rs1, FRM_DYN)>;859def : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU_INX $rs1, FRM_DYN)>;860def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L_INX $rs1, FRM_DYN)>;861def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU_INX $rs1, FRM_DYN)>;862} // Predicates = [HasStdExtZfinx, IsRV64]863