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-exception 6// 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_RV64 19 : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>; 20def SDT_RISCVFMV_X_ANYEXTW_RV64 21 : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>; 22def STD_RISCVFCVT_W_RV64 23 : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisFP<1>]>; 24def STD_RISCVFCVT_X 25 : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>; 26 27def riscv_fmv_w_x_rv64 28 : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>; 29def riscv_fmv_x_anyextw_rv64 30 : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>; 31def riscv_fcvt_w_rtz_rv64 32 : SDNode<"RISCVISD::FCVT_W_RTZ_RV64", STD_RISCVFCVT_W_RV64>; 33def riscv_fcvt_wu_rtz_rv64 34 : SDNode<"RISCVISD::FCVT_WU_RTZ_RV64", STD_RISCVFCVT_W_RV64>; 35def riscv_fcvt_x_rtz 36 : SDNode<"RISCVISD::FCVT_X_RTZ", STD_RISCVFCVT_X>; 37def riscv_fcvt_xu_rtz 38 : SDNode<"RISCVISD::FCVT_XU_RTZ", STD_RISCVFCVT_X>; 39 40//===----------------------------------------------------------------------===// 41// Operand and SDNode transformation definitions. 42//===----------------------------------------------------------------------===// 43 44// Floating-point rounding mode 45 46def FRMArg : AsmOperandClass { 47 let Name = "FRMArg"; 48 let RenderMethod = "addFRMArgOperands"; 49 let DiagnosticType = "InvalidFRMArg"; 50} 51 52def frmarg : Operand<XLenVT> { 53 let ParserMatchClass = FRMArg; 54 let PrintMethod = "printFRMArg"; 55 let DecoderMethod = "decodeFRMArg"; 56} 57 58//===----------------------------------------------------------------------===// 59// Instruction class templates 60//===----------------------------------------------------------------------===// 61 62let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 63class FPFMAS_rrr_frm<RISCVOpcode opcode, string opcodestr> 64 : RVInstR4Frm<0b00, opcode, (outs FPR32:$rd), 65 (ins FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, frmarg:$funct3), 66 opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">; 67 68class FPFMASDynFrmAlias<FPFMAS_rrr_frm Inst, string OpcodeStr> 69 : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3", 70 (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 71 72let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 73class FPALUS_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 74 : RVInstR<funct7, funct3, OPC_OP_FP, (outs FPR32:$rd), 75 (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">; 76 77let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 78class FPALUS_rr_frm<bits<7> funct7, string opcodestr> 79 : RVInstRFrm<funct7, OPC_OP_FP, (outs FPR32:$rd), 80 (ins FPR32:$rs1, FPR32:$rs2, frmarg:$funct3), opcodestr, 81 "$rd, $rs1, $rs2, $funct3">; 82 83class FPALUSDynFrmAlias<FPALUS_rr_frm Inst, string OpcodeStr> 84 : InstAlias<OpcodeStr#" $rd, $rs1, $rs2", 85 (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, 0b111)>; 86 87let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 88class FPUnaryOp_r<bits<7> funct7, bits<3> funct3, RegisterClass rdty, 89 RegisterClass rs1ty, string opcodestr> 90 : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1), 91 opcodestr, "$rd, $rs1">; 92 93let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 94class FPUnaryOp_r_frm<bits<7> funct7, RegisterClass rdty, RegisterClass rs1ty, 95 string opcodestr> 96 : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd), 97 (ins rs1ty:$rs1, frmarg:$funct3), opcodestr, 98 "$rd, $rs1, $funct3">; 99 100class FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr, 101 RegisterClass rdty, RegisterClass rs1ty> 102 : InstAlias<OpcodeStr#" $rd, $rs1", 103 (Inst rdty:$rd, rs1ty:$rs1, 0b111)>; 104 105let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 106class FPCmpS_rr<bits<3> funct3, string opcodestr> 107 : RVInstR<0b1010000, funct3, OPC_OP_FP, (outs GPR:$rd), 108 (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">, 109 Sched<[WriteFCmp32, ReadFCmp32, ReadFCmp32]>; 110 111//===----------------------------------------------------------------------===// 112// Instructions 113//===----------------------------------------------------------------------===// 114 115let Predicates = [HasStdExtF] in { 116let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 117def FLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd), 118 (ins GPR:$rs1, simm12:$imm12), 119 "flw", "$rd, ${imm12}(${rs1})">, 120 Sched<[WriteFLD32, ReadFMemBase]>; 121 122// Operands for stores are in the order srcreg, base, offset rather than 123// reflecting the order these fields are specified in the instruction 124// encoding. 125let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 126def FSW : RVInstS<0b010, OPC_STORE_FP, (outs), 127 (ins FPR32:$rs2, GPR:$rs1, simm12:$imm12), 128 "fsw", "$rs2, ${imm12}(${rs1})">, 129 Sched<[WriteFST32, ReadStoreData, ReadFMemBase]>; 130 131def FMADD_S : FPFMAS_rrr_frm<OPC_MADD, "fmadd.s">, 132 Sched<[WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32]>; 133def : FPFMASDynFrmAlias<FMADD_S, "fmadd.s">; 134def FMSUB_S : FPFMAS_rrr_frm<OPC_MSUB, "fmsub.s">, 135 Sched<[WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32]>; 136def : FPFMASDynFrmAlias<FMSUB_S, "fmsub.s">; 137def FNMSUB_S : FPFMAS_rrr_frm<OPC_NMSUB, "fnmsub.s">, 138 Sched<[WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32]>; 139def : FPFMASDynFrmAlias<FNMSUB_S, "fnmsub.s">; 140def FNMADD_S : FPFMAS_rrr_frm<OPC_NMADD, "fnmadd.s">, 141 Sched<[WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32]>; 142def : FPFMASDynFrmAlias<FNMADD_S, "fnmadd.s">; 143 144def FADD_S : FPALUS_rr_frm<0b0000000, "fadd.s">, 145 Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 146def : FPALUSDynFrmAlias<FADD_S, "fadd.s">; 147def FSUB_S : FPALUS_rr_frm<0b0000100, "fsub.s">, 148 Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 149def : FPALUSDynFrmAlias<FSUB_S, "fsub.s">; 150def FMUL_S : FPALUS_rr_frm<0b0001000, "fmul.s">, 151 Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>; 152def : FPALUSDynFrmAlias<FMUL_S, "fmul.s">; 153def FDIV_S : FPALUS_rr_frm<0b0001100, "fdiv.s">, 154 Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>; 155def : FPALUSDynFrmAlias<FDIV_S, "fdiv.s">; 156 157def FSQRT_S : FPUnaryOp_r_frm<0b0101100, FPR32, FPR32, "fsqrt.s">, 158 Sched<[WriteFSqrt32, ReadFSqrt32]> { 159 let rs2 = 0b00000; 160} 161def : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>; 162 163def FSGNJ_S : FPALUS_rr<0b0010000, 0b000, "fsgnj.s">, 164 Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>; 165def FSGNJN_S : FPALUS_rr<0b0010000, 0b001, "fsgnjn.s">, 166 Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>; 167def FSGNJX_S : FPALUS_rr<0b0010000, 0b010, "fsgnjx.s">, 168 Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>; 169def FMIN_S : FPALUS_rr<0b0010100, 0b000, "fmin.s">, 170 Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>; 171def FMAX_S : FPALUS_rr<0b0010100, 0b001, "fmax.s">, 172 Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>; 173 174def FCVT_W_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.w.s">, 175 Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> { 176 let rs2 = 0b00000; 177} 178def : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>; 179 180def FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.wu.s">, 181 Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> { 182 let rs2 = 0b00001; 183} 184def : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>; 185 186def FMV_X_W : FPUnaryOp_r<0b1110000, 0b000, GPR, FPR32, "fmv.x.w">, 187 Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]> { 188 let rs2 = 0b00000; 189} 190 191def FEQ_S : FPCmpS_rr<0b010, "feq.s">; 192def FLT_S : FPCmpS_rr<0b001, "flt.s">; 193def FLE_S : FPCmpS_rr<0b000, "fle.s">; 194 195def FCLASS_S : FPUnaryOp_r<0b1110000, 0b001, GPR, FPR32, "fclass.s">, 196 Sched<[WriteFClass32, ReadFClass32]> { 197 let rs2 = 0b00000; 198} 199 200def FCVT_S_W : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.w">, 201 Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> { 202 let rs2 = 0b00000; 203} 204def : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>; 205 206def FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.wu">, 207 Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> { 208 let rs2 = 0b00001; 209} 210def : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>; 211 212def FMV_W_X : FPUnaryOp_r<0b1111000, 0b000, FPR32, GPR, "fmv.w.x">, 213 Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]> { 214 let rs2 = 0b00000; 215} 216} // Predicates = [HasStdExtF] 217 218let Predicates = [HasStdExtF, IsRV64] in { 219def FCVT_L_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.l.s">, 220 Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> { 221 let rs2 = 0b00010; 222} 223def : FPUnaryOpDynFrmAlias<FCVT_L_S, "fcvt.l.s", GPR, FPR32>; 224 225def FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.lu.s">, 226 Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> { 227 let rs2 = 0b00011; 228} 229def : FPUnaryOpDynFrmAlias<FCVT_LU_S, "fcvt.lu.s", GPR, FPR32>; 230 231def FCVT_S_L : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.l">, 232 Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> { 233 let rs2 = 0b00010; 234} 235def : FPUnaryOpDynFrmAlias<FCVT_S_L, "fcvt.s.l", FPR32, GPR>; 236 237def FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.lu">, 238 Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> { 239 let rs2 = 0b00011; 240} 241def : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>; 242} // Predicates = [HasStdExtF, IsRV64] 243 244//===----------------------------------------------------------------------===// 245// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 246//===----------------------------------------------------------------------===// 247 248let Predicates = [HasStdExtF] in { 249def : InstAlias<"flw $rd, (${rs1})", (FLW FPR32:$rd, GPR:$rs1, 0), 0>; 250def : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>; 251 252def : InstAlias<"fmv.s $rd, $rs", (FSGNJ_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 253def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 254def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 255 256// fgt.s/fge.s are recognised by the GNU assembler but the canonical 257// flt.s/fle.s forms will always be printed. Therefore, set a zero weight. 258def : InstAlias<"fgt.s $rd, $rs, $rt", 259 (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 260def : InstAlias<"fge.s $rd, $rs, $rt", 261 (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 262 263// The following csr instructions actually alias instructions from the base ISA. 264// However, it only makes sense to support them when the F extension is enabled. 265// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr". 266def : InstAlias<"frcsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>; 267def : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>; 268def : InstAlias<"fscsr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 2>; 269 270// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them 271// zero weight. 272def : InstAlias<"frsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>; 273def : InstAlias<"fssr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>; 274def : InstAlias<"fssr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 0>; 275 276def : InstAlias<"frrm $rd", (CSRRS GPR:$rd, SysRegFRM.Encoding, X0), 2>; 277def : InstAlias<"fsrm $rd, $rs", (CSRRW GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>; 278def : InstAlias<"fsrm $rs", (CSRRW X0, SysRegFRM.Encoding, GPR:$rs), 2>; 279def : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>; 280def : InstAlias<"fsrmi $imm", (CSRRWI X0, SysRegFRM.Encoding, uimm5:$imm), 2>; 281 282def : InstAlias<"frflags $rd", (CSRRS GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>; 283def : InstAlias<"fsflags $rd, $rs", (CSRRW GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>; 284def : InstAlias<"fsflags $rs", (CSRRW X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>; 285def : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>; 286def : InstAlias<"fsflagsi $imm", (CSRRWI X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>; 287 288// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both 289// spellings should be supported by standard tools. 290def : MnemonicAlias<"fmv.s.x", "fmv.w.x">; 291def : MnemonicAlias<"fmv.x.s", "fmv.x.w">; 292 293def PseudoFLW : PseudoFloatLoad<"flw", FPR32>; 294def PseudoFSW : PseudoStore<"fsw", FPR32>; 295} // Predicates = [HasStdExtF] 296 297//===----------------------------------------------------------------------===// 298// Pseudo-instructions and codegen patterns 299//===----------------------------------------------------------------------===// 300 301/// Floating point constants 302def fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>; 303 304/// Generic pattern classes 305class PatFpr32Fpr32<SDPatternOperator OpNode, RVInstR Inst> 306 : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2)>; 307 308class PatFpr32Fpr32DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst> 309 : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2, 0b111)>; 310 311let Predicates = [HasStdExtF] in { 312 313/// Float constants 314def : Pat<(f32 (fpimm0)), (FMV_W_X X0)>; 315 316/// Float conversion operations 317 318// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so 319// are defined later. 320 321/// Float arithmetic operations 322 323def : PatFpr32Fpr32DynFrm<fadd, FADD_S>; 324def : PatFpr32Fpr32DynFrm<fsub, FSUB_S>; 325def : PatFpr32Fpr32DynFrm<fmul, FMUL_S>; 326def : PatFpr32Fpr32DynFrm<fdiv, FDIV_S>; 327 328def : Pat<(fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, 0b111)>; 329 330def : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>; 331def : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>; 332 333def : PatFpr32Fpr32<fcopysign, FSGNJ_S>; 334def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>; 335 336// fmadd: rs1 * rs2 + rs3 337def : Pat<(fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3), 338 (FMADD_S $rs1, $rs2, $rs3, 0b111)>; 339 340// fmsub: rs1 * rs2 - rs3 341def : Pat<(fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)), 342 (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 343 344// fnmsub: -rs1 * rs2 + rs3 345def : Pat<(fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3), 346 (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 347 348// fnmadd: -rs1 * rs2 - rs3 349def : Pat<(fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)), 350 (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 351 352// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches 353// LLVM's fminnum and fmaxnum 354// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>. 355def : PatFpr32Fpr32<fminnum, FMIN_S>; 356def : PatFpr32Fpr32<fmaxnum, FMAX_S>; 357 358/// Setcc 359 360def : PatFpr32Fpr32<seteq, FEQ_S>; 361def : PatFpr32Fpr32<setoeq, FEQ_S>; 362def : PatFpr32Fpr32<setlt, FLT_S>; 363def : PatFpr32Fpr32<setolt, FLT_S>; 364def : PatFpr32Fpr32<setle, FLE_S>; 365def : PatFpr32Fpr32<setole, FLE_S>; 366 367def Select_FPR32_Using_CC_GPR : SelectCC_rrirr<FPR32, GPR>; 368 369/// Loads 370 371defm : LdPat<load, FLW, f32>; 372 373/// Stores 374 375defm : StPat<store, FSW, FPR32, f32>; 376 377} // Predicates = [HasStdExtF] 378 379let Predicates = [HasStdExtF, IsRV32] in { 380// Moves (no conversion) 381def : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>; 382def : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>; 383 384// float->[u]int. Round-to-zero must be used. 385def : Pat<(i32 (fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; 386def : Pat<(i32 (fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; 387 388// Saturating float->[u]int32. 389def : Pat<(i32 (riscv_fcvt_x_rtz FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; 390def : Pat<(i32 (riscv_fcvt_xu_rtz FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; 391 392// float->int32 with current rounding mode. 393def : Pat<(i32 (lrint FPR32:$rs1)), (FCVT_W_S $rs1, 0b111)>; 394 395// float->int32 rounded to nearest with ties rounded away from zero. 396def : Pat<(i32 (lround FPR32:$rs1)), (FCVT_W_S $rs1, 0b100)>; 397 398// [u]int->float. Match GCC and default to using dynamic rounding mode. 399def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, 0b111)>; 400def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, 0b111)>; 401} // Predicates = [HasStdExtF, IsRV32] 402 403let Predicates = [HasStdExtF, IsRV64] in { 404// Moves (no conversion) 405def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>; 406def : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>; 407def : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32), 408 (FMV_X_W FPR32:$src)>; 409 410// Use target specific isd nodes to help us remember the result is sign 411// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be 412// duplicated if it has another user that didn't need the sign_extend. 413def : Pat<(riscv_fcvt_w_rtz_rv64 FPR32:$rs1), (FCVT_W_S $rs1, 0b001)>; 414def : Pat<(riscv_fcvt_wu_rtz_rv64 FPR32:$rs1), (FCVT_WU_S $rs1, 0b001)>; 415 416// float->[u]int64. Round-to-zero must be used. 417def : Pat<(i64 (fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; 418def : Pat<(i64 (fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; 419 420// Saturating float->[u]int64. 421def : Pat<(i64 (riscv_fcvt_x_rtz FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; 422def : Pat<(i64 (riscv_fcvt_xu_rtz FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; 423 424// float->int64 with current rounding mode. 425def : Pat<(i64 (lrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 426def : Pat<(i64 (llrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 427 428// float->int64 rounded to neartest with ties rounded away from zero. 429def : Pat<(i64 (lround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 430def : Pat<(i64 (llround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 431 432// [u]int->fp. Match GCC and default to using dynamic rounding mode. 433def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, 0b111)>; 434def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, 0b111)>; 435def : Pat<(sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, 0b111)>; 436def : Pat<(uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, 0b111)>; 437} // Predicates = [HasStdExtF, IsRV64] 438