[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / Target / RISCV / RISCVInstrInfoF.td
blob52eadbdec25558a9682b0402ce64fcb49eb81210
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.
12 //===----------------------------------------------------------------------===//
14 //===----------------------------------------------------------------------===//
15 // RISC-V specific DAG Nodes.
16 //===----------------------------------------------------------------------===//
18 def SDT_RISCVFMV_W_X_RV64
19     : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
20 def SDT_RISCVFMV_X_ANYEXTW_RV64
21     : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;
22 def SDT_RISCVFCVT_W_RV64
23     : SDTypeProfile<1, 2, [SDTCisVT<0, i64>, SDTCisFP<1>,
24                            SDTCisVT<2, i64>]>;
25 def SDT_RISCVFCVT_X
26     : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>, SDTCisFP<1>,
27                            SDTCisVT<2, XLenVT>]>;
29 def SDT_RISCVFROUND
30     : SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
31                            SDTCisVT<3, XLenVT>]>;
32 def SDT_RISCVFCLASS
33     : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>;
35 def riscv_fclass
36     : SDNode<"RISCVISD::FCLASS", SDT_RISCVFCLASS>;
38 def riscv_fround
39     : SDNode<"RISCVISD::FROUND", SDT_RISCVFROUND>;
41 def riscv_fmv_w_x_rv64
42     : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>;
43 def riscv_fmv_x_anyextw_rv64
44     : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>;
45 def riscv_fcvt_w_rv64
46     : SDNode<"RISCVISD::FCVT_W_RV64", SDT_RISCVFCVT_W_RV64>;
47 def riscv_fcvt_wu_rv64
48     : SDNode<"RISCVISD::FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64>;
49 def riscv_fcvt_x
50     : SDNode<"RISCVISD::FCVT_X", SDT_RISCVFCVT_X>;
51 def riscv_fcvt_xu
52     : SDNode<"RISCVISD::FCVT_XU", SDT_RISCVFCVT_X>;
54 def riscv_fmin : SDNode<"RISCVISD::FMIN", SDTFPBinOp>;
55 def riscv_fmax : SDNode<"RISCVISD::FMAX", SDTFPBinOp>;
57 def riscv_strict_fcvt_w_rv64
58     : SDNode<"RISCVISD::STRICT_FCVT_W_RV64", SDT_RISCVFCVT_W_RV64,
59              [SDNPHasChain]>;
60 def riscv_strict_fcvt_wu_rv64
61     : SDNode<"RISCVISD::STRICT_FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64,
62              [SDNPHasChain]>;
64 def riscv_any_fcvt_w_rv64 : PatFrags<(ops node:$src, node:$frm),
65                                      [(riscv_strict_fcvt_w_rv64 node:$src, node:$frm),
66                                       (riscv_fcvt_w_rv64 node:$src, node:$frm)]>;
67 def riscv_any_fcvt_wu_rv64 : PatFrags<(ops node:$src, node:$frm),
68                                       [(riscv_strict_fcvt_wu_rv64 node:$src, node:$frm),
69                                        (riscv_fcvt_wu_rv64 node:$src, node:$frm)]>;
71 def any_fma_nsz : PatFrag<(ops node:$rs1, node:$rs2, node:$rs3),
72                           (any_fma node:$rs1, node:$rs2, node:$rs3), [{
73   return N->getFlags().hasNoSignedZeros();
74 }]>;
75 //===----------------------------------------------------------------------===//
76 // Operand and SDNode transformation definitions.
77 //===----------------------------------------------------------------------===//
79 // Zfinx
81 def GPRAsFPR : AsmOperandClass {
82   let Name = "GPRAsFPR";
83   let ParserMethod = "parseGPRAsFPR";
84   let RenderMethod = "addRegOperands";
87 def FPR32INX : RegisterOperand<GPRF32> {
88   let ParserMatchClass = GPRAsFPR;
89   let DecoderMethod = "DecodeGPRRegisterClass";
92 // Describes a combination of predicates from F/D/Zfh/Zfhmin or
93 // Zfinx/Zdinx/Zhinx/Zhinxmin that are applied to scalar FP instruction.
94 // Contains the DAGOperand for the primary type for the predicates. The primary
95 // type may be unset for combinations of predicates like Zfh+D.
96 // Also contains the DAGOperand for f16/f32/f64, instruction suffix, and
97 // decoder namespace that go with an instruction given those predicates.
99 // The DAGOperand can be unset if the predicates are not enough to define it.
100 class ExtInfo<string suffix, string space, list<Predicate> predicates,
101               ValueType primaryvt, DAGOperand primaryty, DAGOperand f32ty,
102               DAGOperand f64ty, DAGOperand f16ty> {
103   list<Predicate> Predicates = predicates;
104   string Suffix = suffix;
105   string Space = space;
106   DAGOperand PrimaryTy = primaryty;
107   DAGOperand F16Ty = f16ty;
108   DAGOperand F32Ty = f32ty;
109   DAGOperand F64Ty = f64ty;
110   ValueType PrimaryVT = primaryvt;
113 def FExt       : ExtInfo<"", "", [HasStdExtF], f32, FPR32, FPR32, ?, ?>;
115 def ZfinxExt   : ExtInfo<"_INX", "RVZfinx", [HasStdExtZfinx], f32, FPR32INX, FPR32INX, ?, ?>;
117 defvar FExts   = [FExt, ZfinxExt];
119 // Floating-point rounding mode
121 def FRMArg : AsmOperandClass {
122   let Name = "FRMArg";
123   let RenderMethod = "addFRMArgOperands";
124   let ParserMethod = "parseFRMArg";
125   let IsOptional = 1;
126   let DefaultMethod = "defaultFRMArgOp";
129 def frmarg : Operand<XLenVT> {
130   let ParserMatchClass = FRMArg;
131   let PrintMethod = "printFRMArg";
132   let DecoderMethod = "decodeFRMArg";
135 // Variants of the rounding mode operand that default to 'rne'. This is used
136 // for historical/legacy reasons. fcvt functions where the rounding mode
137 // doesn't affect the output originally always set it to 0b000 ('rne'). As old
138 // versions of LLVM and GCC will fail to decode versions of these instructions
139 // with the rounding mode set to something other than 'rne', we retain this
140 // default.
141 def FRMArgLegacy : AsmOperandClass {
142   let Name = "FRMArgLegacy";
143   let RenderMethod = "addFRMArgOperands";
144   let ParserMethod = "parseFRMArg";
145   let IsOptional = 1;
146   let DefaultMethod = "defaultFRMArgLegacyOp";
149 def frmarglegacy : Operand<XLenVT> {
150   let ParserMatchClass = FRMArgLegacy;
151   let PrintMethod = "printFRMArgLegacy";
152   let DecoderMethod = "decodeFRMArg";
155 //===----------------------------------------------------------------------===//
156 // Instruction class templates
157 //===----------------------------------------------------------------------===//
159 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
160 class FPLoad_r<bits<3> funct3, string opcodestr, DAGOperand rty,
161                SchedWrite sw>
162     : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd),
163               (ins GPRMem:$rs1, simm12:$imm12),
164               opcodestr, "$rd, ${imm12}(${rs1})">,
165       Sched<[sw, ReadFMemBase]>;
167 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
168 class FPStore_r<bits<3> funct3, string opcodestr, DAGOperand rty,
169                 SchedWrite sw>
170     : RVInstS<funct3, OPC_STORE_FP, (outs),
171               (ins rty:$rs2, GPRMem:$rs1, simm12:$imm12),
172               opcodestr, "$rs2, ${imm12}(${rs1})">,
173       Sched<[sw, ReadFStoreData, ReadFMemBase]>;
175 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
176     UseNamedOperandTable = 1, hasPostISelHook = 1, isCommutable = 1 in
177 class FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,
178                     DAGOperand rty>
179     : RVInstR4Frm<funct2, opcode, (outs rty:$rd),
180                   (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm),
181                   opcodestr, "$rd, $rs1, $rs2, $rs3$frm">;
183 multiclass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,
184                            string opcodestr, ExtInfo Ext> {
185   let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
186   def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.PrimaryTy>;
189 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
190 class FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
191                DAGOperand rty, bit Commutable>
192     : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd),
193               (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
194   let isCommutable = Commutable;
196 multiclass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
197                       ExtInfo Ext, bit Commutable = 0> {
198   let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
199   def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
202 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
203     UseNamedOperandTable = 1, hasPostISelHook = 1 in
204 class FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty,
205                    bit Commutable>
206     : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd),
207                  (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr,
208                   "$rd, $rs1, $rs2$frm"> {
209   let isCommutable = Commutable;
211 multiclass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,
212                           ExtInfo Ext, bit Commutable = 0> {
213   let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
214   def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.PrimaryTy, Commutable>;
217 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
218 class FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
219                   DAGOperand rdty, DAGOperand rs1ty, string opcodestr>
220     : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
221               opcodestr, "$rd, $rs1"> {
222   let rs2 = rs2val;
224 multiclass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
225                          ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
226                          string opcodestr> {
227   let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
228   def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, rdty, rs1ty, opcodestr>;
231 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
232     UseNamedOperandTable = 1, hasPostISelHook = 1 in
233 class FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
234                       DAGOperand rs1ty, string opcodestr>
235     : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
236                  (ins rs1ty:$rs1, frmarg:$frm), opcodestr,
237                   "$rd, $rs1$frm"> {
238   let rs2 = rs2val;
240 multiclass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,
241                              ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
242                              string opcodestr, list<Predicate> ExtraPreds = []> {
243   let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
244       DecoderNamespace = Ext.Space in
245   def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, rdty, rs1ty,
246                                    opcodestr>;
249 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
250     UseNamedOperandTable = 1, hasPostISelHook = 1 in
251 class FPUnaryOp_r_frmlegacy<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
252                             DAGOperand rs1ty, string opcodestr>
253     : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
254                  (ins rs1ty:$rs1, frmarglegacy:$frm), opcodestr,
255                   "$rd, $rs1$frm"> {
256   let rs2 = rs2val;
258 multiclass FPUnaryOp_r_frmlegacy_m<bits<7> funct7, bits<5> rs2val,
259                                    ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
260                                    string opcodestr, list<Predicate> ExtraPreds = []> {
261   let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
262       DecoderNamespace = Ext.Space in
263   def Ext.Suffix : FPUnaryOp_r_frmlegacy<funct7, rs2val, rdty, rs1ty,
264                                          opcodestr>;
267 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
268     IsSignExtendingOpW = 1 in
269 class FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
270                DAGOperand rty, bit Commutable = 0>
271     : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd),
272               (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
273   let isCommutable = Commutable;
275 multiclass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
276                       ExtInfo Ext, bit Commutable = 0> {
277   let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
278   def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
281 class PseudoFROUND<DAGOperand Ty, ValueType vt>
282     : Pseudo<(outs Ty:$rd), (ins Ty:$rs1, Ty:$rs2, ixlenimm:$rm),
283       [(set Ty:$rd, (vt (riscv_fround Ty:$rs1, Ty:$rs2, timm:$rm)))]> {
284   let hasSideEffects = 0;
285   let mayLoad = 0;
286   let mayStore = 0;
287   let usesCustomInserter = 1;
288   let mayRaiseFPException = 1;
291 //===----------------------------------------------------------------------===//
292 // Instructions
293 //===----------------------------------------------------------------------===//
295 let Predicates = [HasStdExtF] in {
296 def FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;
298 // Operands for stores are in the order srcreg, base, offset rather than
299 // reflecting the order these fields are specified in the instruction
300 // encoding.
301 def FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;
302 } // Predicates = [HasStdExtF]
304 foreach Ext = FExts in {
305   let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32Addend] in {
306     defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  Ext>;
307     defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  Ext>;
308     defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", Ext>;
309     defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", Ext>;
310   }
312   let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {
313     defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, Commutable=1>;
314     defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>;
315   }
317   let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
318   defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, Commutable=1>;
320   let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
321   defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>;
323   defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, Ext, Ext.PrimaryTy,
324                                    Ext.PrimaryTy, "fsqrt.s">,
325                  Sched<[WriteFSqrt32, ReadFSqrt32]>;
327   let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
328       mayRaiseFPException = 0 in {
329     defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  Ext>;
330     defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", Ext>;
331     defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", Ext>;
332   }
334   let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
335     defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, Commutable=1>;
336     defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, Commutable=1>;
337   }
339   let IsSignExtendingOpW = 1 in
340   defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, Ext, GPR, Ext.PrimaryTy,
341                                     "fcvt.w.s">,
342                   Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
344   let IsSignExtendingOpW = 1 in
345   defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, Ext, GPR, Ext.PrimaryTy,
346                                      "fcvt.wu.s">,
347                    Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
349   let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
350   defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, Commutable=1>;
351   defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>;
352   defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>;
353   }
355   let mayRaiseFPException = 0 in
356   defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
357                                 "fclass.s">,
358                   Sched<[WriteFClass32, ReadFClass32]>;
360   defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, Ext, Ext.PrimaryTy, GPR,
361                                     "fcvt.s.w">,
362                   Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
364   defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, Ext, Ext.PrimaryTy, GPR,
365                                      "fcvt.s.wu">,
366                    Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
368   defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, Ext, GPR, Ext.PrimaryTy,
369                                      "fcvt.l.s", [IsRV64]>,
370                    Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
372   defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, Ext, GPR, Ext.PrimaryTy,
373                                       "fcvt.lu.s", [IsRV64]>,
374                     Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
376   defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, Ext, Ext.PrimaryTy, GPR,
377                                     "fcvt.s.l", [IsRV64]>,
378                   Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
380   defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, Ext, Ext.PrimaryTy, GPR,
381                                      "fcvt.s.lu", [IsRV64]>,
382                    Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
383 } // foreach Ext = FExts
385 let Predicates = [HasStdExtF], mayRaiseFPException = 0,
386     IsSignExtendingOpW = 1 in
387 def FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,
388               Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;
390 let Predicates = [HasStdExtF], mayRaiseFPException = 0 in
391 def FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,
392               Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;
394 //===----------------------------------------------------------------------===//
395 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
396 //===----------------------------------------------------------------------===//
398 let Predicates = [HasStdExtF] in {
399 def : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;
400 def : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;
402 def : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
403 def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
404 def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
406 // fgt.s/fge.s are recognised by the GNU assembler but the canonical
407 // flt.s/fle.s forms will always be printed. Therefore, set a zero weight.
408 def : InstAlias<"fgt.s $rd, $rs, $rt",
409                 (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
410 def : InstAlias<"fge.s $rd, $rs, $rt",
411                 (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
413 // The following csr instructions actually alias instructions from the base ISA.
414 // However, it only makes sense to support them when the F extension is enabled.
415 // NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr".
416 def : InstAlias<"frcsr $rd",      (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>;
417 def : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>;
418 def : InstAlias<"fscsr $rs",      (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 2>;
420 // frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them
421 // zero weight.
422 def : InstAlias<"frsr $rd",       (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>;
423 def : InstAlias<"fssr $rd, $rs",  (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>;
424 def : InstAlias<"fssr $rs",       (CSRRW      X0, SysRegFCSR.Encoding, GPR:$rs), 0>;
426 def : InstAlias<"frrm $rd",        (CSRRS  GPR:$rd, SysRegFRM.Encoding, X0), 2>;
427 def : InstAlias<"fsrm $rd, $rs",   (CSRRW  GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>;
428 def : InstAlias<"fsrm $rs",        (CSRRW       X0, SysRegFRM.Encoding, GPR:$rs), 2>;
429 def : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>;
430 def : InstAlias<"fsrmi $imm",      (CSRRWI      X0, SysRegFRM.Encoding, uimm5:$imm), 2>;
432 def : InstAlias<"frflags $rd",        (CSRRS  GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>;
433 def : InstAlias<"fsflags $rd, $rs",   (CSRRW  GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>;
434 def : InstAlias<"fsflags $rs",        (CSRRW       X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>;
435 def : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>;
436 def : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>;
438 // fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both
439 // spellings should be supported by standard tools.
440 def : MnemonicAlias<"fmv.s.x", "fmv.w.x">;
441 def : MnemonicAlias<"fmv.x.s", "fmv.x.w">;
443 def PseudoFLW  : PseudoFloatLoad<"flw", FPR32>;
444 def PseudoFSW  : PseudoStore<"fsw", FPR32>;
445 let usesCustomInserter = 1 in {
446 def PseudoQuietFLE_S : PseudoQuietFCMP<FPR32>;
447 def PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>;
449 } // Predicates = [HasStdExtF]
451 let Predicates = [HasStdExtZfinx] in {
452 def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
453 def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
455 def : InstAlias<"fgt.s $rd, $rs, $rt",
456                 (FLT_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
457 def : InstAlias<"fge.s $rd, $rs, $rt",
458                 (FLE_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
459 let usesCustomInserter = 1 in {
460 def PseudoQuietFLE_S_INX : PseudoQuietFCMP<FPR32INX>;
461 def PseudoQuietFLT_S_INX : PseudoQuietFCMP<FPR32INX>;
463 } // Predicates = [HasStdExtZfinx]
465 //===----------------------------------------------------------------------===//
466 // Pseudo-instructions and codegen patterns
467 //===----------------------------------------------------------------------===//
469 defvar FRM_RNE = 0b000;
470 defvar FRM_RTZ = 0b001;
471 defvar FRM_RDN = 0b010;
472 defvar FRM_RUP = 0b011;
473 defvar FRM_RMM = 0b100;
474 defvar FRM_DYN = 0b111;
476 /// Floating point constants
477 def fpimm0    : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
479 /// Generic pattern classes
480 class PatSetCC<DAGOperand Ty, SDPatternOperator OpNode, CondCode Cond,
481                RVInst Inst, ValueType vt>
482     : Pat<(XLenVT (OpNode (vt Ty:$rs1), Ty:$rs2, Cond)), (Inst $rs1, $rs2)>;
483 multiclass PatSetCC_m<SDPatternOperator OpNode, CondCode Cond,
484                       RVInst Inst, ExtInfo Ext> {
485   let Predicates = Ext.Predicates in
486   def Ext.Suffix : PatSetCC<Ext.PrimaryTy, OpNode, Cond,
487                             !cast<RVInst>(Inst#Ext.Suffix), Ext.PrimaryVT>;
490 class PatFprFpr<SDPatternOperator OpNode, RVInstR Inst,
491                 DAGOperand RegTy, ValueType vt>
492     : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2)>;
493 multiclass PatFprFpr_m<SDPatternOperator OpNode, RVInstR Inst,
494                        ExtInfo Ext> {
495   let Predicates = Ext.Predicates in
496   def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),
497                              Ext.PrimaryTy, Ext.PrimaryVT>;
500 class PatFprFprDynFrm<SDPatternOperator OpNode, RVInstRFrm Inst,
501                       DAGOperand RegTy, ValueType vt>
502     : Pat<(OpNode (vt RegTy:$rs1), (vt RegTy:$rs2)), (Inst $rs1, $rs2, FRM_DYN)>;
503 multiclass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,
504                              ExtInfo Ext> {
505   let Predicates = Ext.Predicates in
506   def Ext.Suffix : PatFprFprDynFrm<OpNode,
507                                    !cast<RVInstRFrm>(Inst#Ext.Suffix),
508                                    Ext.PrimaryTy, Ext.PrimaryVT>;
511 /// Float conversion operations
513 // [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so
514 // are defined later.
516 /// Float arithmetic operations
517 foreach Ext = FExts in {
518   defm : PatFprFprDynFrm_m<any_fadd, FADD_S, Ext>;
519   defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, Ext>;
520   defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, Ext>;
521   defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, Ext>;
524 let Predicates = [HasStdExtF] in {
525 def : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;
527 def : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;
528 def : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;
530 def : Pat<(riscv_fclass FPR32:$rs1), (FCLASS_S $rs1)>;
531 } // Predicates = [HasStdExtF]
533 let Predicates = [HasStdExtZfinx] in {
534 def : Pat<(any_fsqrt FPR32INX:$rs1), (FSQRT_S_INX FPR32INX:$rs1, FRM_DYN)>;
536 def : Pat<(fneg FPR32INX:$rs1), (FSGNJN_S_INX $rs1, $rs1)>;
537 def : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>;
539 def : Pat<(riscv_fclass FPR32INX:$rs1), (FCLASS_S_INX $rs1)>;
540 } // Predicates = [HasStdExtZfinx]
542 foreach Ext = FExts in
543 defm : PatFprFpr_m<fcopysign, FSGNJ_S, Ext>;
545 let Predicates = [HasStdExtF] in {
546 def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;
548 // fmadd: rs1 * rs2 + rs3
549 def : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3),
550           (FMADD_S $rs1, $rs2, $rs3, FRM_DYN)>;
552 // fmsub: rs1 * rs2 - rs3
553 def : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)),
554           (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
556 // fnmsub: -rs1 * rs2 + rs3
557 def : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3),
558           (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
560 // fnmadd: -rs1 * rs2 - rs3
561 def : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)),
562           (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
564 // fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
565 def : Pat<(fneg (any_fma_nsz FPR32:$rs1, FPR32:$rs2, FPR32:$rs3)),
566           (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, FRM_DYN)>;
567 } // Predicates = [HasStdExtF]
569 let Predicates = [HasStdExtZfinx] in {
570 def : Pat<(fcopysign FPR32INX:$rs1, (fneg FPR32INX:$rs2)), (FSGNJN_S_INX $rs1, $rs2)>;
572 // fmadd: rs1 * rs2 + rs3
573 def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3),
574           (FMADD_S_INX $rs1, $rs2, $rs3, FRM_DYN)>;
576 // fmsub: rs1 * rs2 - rs3
577 def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
578           (FMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
580 // fnmsub: -rs1 * rs2 + rs3
581 def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, FPR32INX:$rs3),
582           (FNMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
584 // fnmadd: -rs1 * rs2 - rs3
585 def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, (fneg FPR32INX:$rs3)),
586           (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
588 // fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
589 def : Pat<(fneg (any_fma_nsz FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3)),
590           (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, FRM_DYN)>;
591 } // Predicates = [HasStdExtZfinx]
593 // The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
594 // LLVM's fminnum and fmaxnum
595 // <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
596 foreach Ext = FExts in {
597   defm : PatFprFpr_m<fminnum, FMIN_S, Ext>;
598   defm : PatFprFpr_m<fmaxnum, FMAX_S, Ext>;
599   defm : PatFprFpr_m<riscv_fmin, FMIN_S, Ext>;
600   defm : PatFprFpr_m<riscv_fmax, FMAX_S, Ext>;
603 /// Setcc
604 // FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
605 // strict versions of those.
607 // Match non-signaling FEQ_S
608 foreach Ext = FExts in {
609   defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            Ext>;
610   defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            Ext>;
611   defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, Ext>;
612   defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, Ext>;
613   defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, Ext>;
614   defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, Ext>;
617 let Predicates = [HasStdExtF] in {
618 // Match signaling FEQ_S
619 def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETEQ)),
620           (AND (FLE_S $rs1, $rs2),
621                (FLE_S $rs2, $rs1))>;
622 def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETOEQ)),
623           (AND (FLE_S $rs1, $rs2),
624                (FLE_S $rs2, $rs1))>;
625 // If both operands are the same, use a single FLE.
626 def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETEQ)),
627           (FLE_S $rs1, $rs1)>;
628 def : Pat<(XLenVT (strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETOEQ)),
629           (FLE_S $rs1, $rs1)>;
630 } // Predicates = [HasStdExtF]
632 let Predicates = [HasStdExtZfinx] in {
633 // Match signaling FEQ_S
634 def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETEQ)),
635           (AND (FLE_S_INX $rs1, $rs2),
636                (FLE_S_INX $rs2, $rs1))>;
637 def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs2, SETOEQ)),
638           (AND (FLE_S_INX $rs1, $rs2),
639                (FLE_S_INX $rs2, $rs1))>;
640 // If both operands are the same, use a single FLE.
641 def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETEQ)),
642           (FLE_S_INX $rs1, $rs1)>;
643 def : Pat<(XLenVT (strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETOEQ)),
644           (FLE_S_INX $rs1, $rs1)>;
645 } // Predicates = [HasStdExtZfinx]
647 foreach Ext = FExts in {
648   defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, Ext>;
649   defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, Ext>;
650   defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, Ext>;
651   defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, Ext>;
654 let Predicates = [HasStdExtF] in {
655 defm Select_FPR32 : SelectCC_GPR_rrirr<FPR32, f32>;
657 def PseudoFROUND_S : PseudoFROUND<FPR32, f32>;
659 /// Loads
661 def : LdPat<load, FLW, f32>;
663 /// Stores
665 def : StPat<store, FSW, FPR32, f32>;
667 } // Predicates = [HasStdExtF]
669 let Predicates = [HasStdExtZfinx] in {
670 defm Select_FPR32INX : SelectCC_GPR_rrirr<FPR32INX, f32>;
672 def PseudoFROUND_S_INX : PseudoFROUND<FPR32INX, f32>;
674 /// Loads
675 def : Pat<(f32 (load (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))),
676           (COPY_TO_REGCLASS (LW GPR:$rs1, simm12:$imm12), GPRF32)>;
678 /// Stores
679 def : Pat<(store (f32 FPR32INX:$rs2), (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12)),
680           (SW (COPY_TO_REGCLASS FPR32INX:$rs2, GPR), GPR:$rs1, simm12:$imm12)>;
681 } // Predicates = [HasStdExtZfinx]
683 let Predicates = [HasStdExtF] in {
684 // Moves (no conversion)
685 def : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>;
686 def : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>;
687 } // Predicates = [HasStdExtF]
689 let Predicates = [HasStdExtZfinx] in {
690 // Moves (no conversion)
691 def : Pat<(f32 (bitconvert (i32 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPRF32)>;
692 def : Pat<(i32 (bitconvert FPR32INX:$rs1)), (COPY_TO_REGCLASS FPR32INX:$rs1, GPR)>;
693 } // Predicates = [HasStdExtZfinx]
695 let Predicates = [HasStdExtF] in {
696 // float->[u]int. Round-to-zero must be used.
697 def : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RTZ)>;
698 def : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, FRM_RTZ)>;
700 // Saturating float->[u]int32.
701 def : Pat<(i32 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_W_S $rs1, timm:$frm)>;
702 def : Pat<(i32 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_WU_S $rs1, timm:$frm)>;
704 // float->int32 with current rounding mode.
705 def : Pat<(i32 (any_lrint FPR32:$rs1)), (FCVT_W_S $rs1, FRM_DYN)>;
707 // float->int32 rounded to nearest with ties rounded away from zero.
708 def : Pat<(i32 (any_lround FPR32:$rs1)), (FCVT_W_S $rs1, FRM_RMM)>;
710 // [u]int->float. Match GCC and default to using dynamic rounding mode.
711 def : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, FRM_DYN)>;
712 def : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, FRM_DYN)>;
713 } // Predicates = [HasStdExtF]
715 let Predicates = [HasStdExtZfinx] in {
716 // float->[u]int. Round-to-zero must be used.
717 def : Pat<(i32 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RTZ)>;
718 def : Pat<(i32 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_WU_S_INX $rs1, FRM_RTZ)>;
720 // Saturating float->[u]int32.
721 def : Pat<(i32 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_W_S_INX $rs1, timm:$frm)>;
722 def : Pat<(i32 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_WU_S_INX $rs1, timm:$frm)>;
724 // float->int32 with current rounding mode.
725 def : Pat<(i32 (any_lrint FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_DYN)>;
727 // float->int32 rounded to nearest with ties rounded away from zero.
728 def : Pat<(i32 (any_lround FPR32INX:$rs1)), (FCVT_W_S_INX $rs1, FRM_RMM)>;
730 // [u]int->float. Match GCC and default to using dynamic rounding mode.
731 def : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W_INX $rs1, FRM_DYN)>;
732 def : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
733 } // Predicates = [HasStdExtZfinx]
735 let Predicates = [HasStdExtF, IsRV64] in {
736 // Moves (no conversion)
737 def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>;
738 def : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;
740 // Use target specific isd nodes to help us remember the result is sign
741 // extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
742 // duplicated if it has another user that didn't need the sign_extend.
743 def : Pat<(riscv_any_fcvt_w_rv64 FPR32:$rs1, timm:$frm),  (FCVT_W_S $rs1, timm:$frm)>;
744 def : Pat<(riscv_any_fcvt_wu_rv64 FPR32:$rs1, timm:$frm), (FCVT_WU_S $rs1, timm:$frm)>;
746 // float->[u]int64. Round-to-zero must be used.
747 def : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RTZ)>;
748 def : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, FRM_RTZ)>;
750 // Saturating float->[u]int64.
751 def : Pat<(i64 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_L_S $rs1, timm:$frm)>;
752 def : Pat<(i64 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_LU_S $rs1, timm:$frm)>;
754 // float->int64 with current rounding mode.
755 def : Pat<(i64 (any_lrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
756 def : Pat<(i64 (any_llrint FPR32:$rs1)), (FCVT_L_S $rs1, FRM_DYN)>;
758 // float->int64 rounded to neartest with ties rounded away from zero.
759 def : Pat<(i64 (any_lround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
760 def : Pat<(i64 (any_llround FPR32:$rs1)), (FCVT_L_S $rs1, FRM_RMM)>;
762 // [u]int->fp. Match GCC and default to using dynamic rounding mode.
763 def : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, FRM_DYN)>;
764 def : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, FRM_DYN)>;
765 def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, FRM_DYN)>;
766 def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, FRM_DYN)>;
767 } // Predicates = [HasStdExtF, IsRV64]
769 let Predicates = [HasStdExtZfinx, IsRV64] in {
770 // Moves (no conversion)
771 def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (COPY_TO_REGCLASS GPR:$src, GPRF32)>;
772 def : Pat<(riscv_fmv_x_anyextw_rv64 GPRF32:$src), (COPY_TO_REGCLASS GPRF32:$src, GPR)>;
774 // Use target specific isd nodes to help us remember the result is sign
775 // extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
776 // duplicated if it has another user that didn't need the sign_extend.
777 def : Pat<(riscv_any_fcvt_w_rv64 FPR32INX:$rs1, timm:$frm),  (FCVT_W_S_INX $rs1, timm:$frm)>;
778 def : Pat<(riscv_any_fcvt_wu_rv64 FPR32INX:$rs1, timm:$frm), (FCVT_WU_S_INX $rs1, timm:$frm)>;
780 // float->[u]int64. Round-to-zero must be used.
781 def : Pat<(i64 (any_fp_to_sint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_RTZ)>;
782 def : Pat<(i64 (any_fp_to_uint FPR32INX:$rs1)), (FCVT_LU_S_INX $rs1, FRM_RTZ)>;
784 // Saturating float->[u]int64.
785 def : Pat<(i64 (riscv_fcvt_x FPR32INX:$rs1, timm:$frm)), (FCVT_L_S_INX $rs1, timm:$frm)>;
786 def : Pat<(i64 (riscv_fcvt_xu FPR32INX:$rs1, timm:$frm)), (FCVT_LU_S_INX $rs1, timm:$frm)>;
788 // float->int64 with current rounding mode.
789 def : Pat<(i64 (any_lrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
790 def : Pat<(i64 (any_llrint FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
792 // float->int64 rounded to neartest with ties rounded away from zero.
793 def : Pat<(i64 (any_lround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
794 def : Pat<(i64 (any_llround FPR32INX:$rs1)), (FCVT_L_S_INX $rs1, FRM_DYN)>;
796 // [u]int->fp. Match GCC and default to using dynamic rounding mode.
797 def : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W_INX $rs1, FRM_DYN)>;
798 def : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU_INX $rs1, FRM_DYN)>;
799 def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L_INX $rs1, FRM_DYN)>;
800 def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU_INX $rs1, FRM_DYN)>;
801 } // Predicates = [HasStdExtZfinx, IsRV64]