1//===-- RISCVInstrInfoFH.td - RISC-V 'FH' 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 'Zfh'
10// half-precision floating-point extension, version 0.1.
11// This version is still experimental as the 'Zfh' extension hasn't been
12// ratified yet.
13//
14//===----------------------------------------------------------------------===//
15
16//===----------------------------------------------------------------------===//
17// RISC-V specific DAG Nodes.
18//===----------------------------------------------------------------------===//
19
20def SDT_RISCVFMV_H_X
21    : SDTypeProfile<1, 1, [SDTCisVT<0, f16>, SDTCisVT<1, XLenVT>]>;
22def SDT_RISCVFMV_X_ANYEXTH
23    : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisVT<1, f16>]>;
24
25def riscv_fmv_h_x
26    : SDNode<"RISCVISD::FMV_H_X", SDT_RISCVFMV_H_X>;
27def riscv_fmv_x_anyexth
28    : SDNode<"RISCVISD::FMV_X_ANYEXTH", SDT_RISCVFMV_X_ANYEXTH>;
29
30//===----------------------------------------------------------------------===//
31// Instruction class templates
32//===----------------------------------------------------------------------===//
33
34let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
35class FPFMAH_rrr_frm<RISCVOpcode opcode, string opcodestr>
36    : RVInstR4Frm<0b10, opcode, (outs FPR16:$rd),
37                  (ins FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, frmarg:$funct3),
38                  opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
39
40class FPFMAHDynFrmAlias<FPFMAH_rrr_frm Inst, string OpcodeStr>
41    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
42                (Inst FPR16:$rd, FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, 0b111)>;
43
44let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
45class FPALUH_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
46    : RVInstR<funct7, funct3, OPC_OP_FP, (outs FPR16:$rd),
47              (ins FPR16:$rs1, FPR16:$rs2), opcodestr, "$rd, $rs1, $rs2">;
48
49let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
50class FPALUH_rr_frm<bits<7> funct7, string opcodestr>
51    : RVInstRFrm<funct7, OPC_OP_FP, (outs FPR16:$rd),
52                 (ins FPR16:$rs1, FPR16:$rs2, frmarg:$funct3), opcodestr,
53                  "$rd, $rs1, $rs2, $funct3">;
54
55class FPALUHDynFrmAlias<FPALUH_rr_frm Inst, string OpcodeStr>
56    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
57                (Inst FPR16:$rd, FPR16:$rs1, FPR16:$rs2, 0b111)>;
58
59let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
60class FPCmpH_rr<bits<3> funct3, string opcodestr>
61    : RVInstR<0b1010010, funct3, OPC_OP_FP, (outs GPR:$rd),
62              (ins FPR16:$rs1, FPR16:$rs2), opcodestr, "$rd, $rs1, $rs2">,
63      Sched<[WriteFCmp16, ReadFCmp16, ReadFCmp16]>;
64
65//===----------------------------------------------------------------------===//
66// Instructions
67//===----------------------------------------------------------------------===//
68
69let Predicates = [HasStdExtZfh] in {
70let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
71def FLH : RVInstI<0b001, OPC_LOAD_FP, (outs FPR16:$rd),
72                  (ins GPR:$rs1, simm12:$imm12),
73                   "flh", "$rd, ${imm12}(${rs1})">,
74          Sched<[WriteFLD16, ReadFMemBase]>;
75
76// Operands for stores are in the order srcreg, base, offset rather than
77// reflecting the order these fields are specified in the instruction
78// encoding.
79let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
80def FSH : RVInstS<0b001, OPC_STORE_FP, (outs),
81                  (ins FPR16:$rs2, GPR:$rs1, simm12:$imm12),
82                   "fsh", "$rs2, ${imm12}(${rs1})">,
83          Sched<[WriteFST16, ReadStoreData, ReadFMemBase]>;
84
85def FMADD_H  : FPFMAH_rrr_frm<OPC_MADD, "fmadd.h">,
86               Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
87def          : FPFMAHDynFrmAlias<FMADD_H, "fmadd.h">;
88def FMSUB_H  : FPFMAH_rrr_frm<OPC_MSUB, "fmsub.h">,
89               Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
90def          : FPFMAHDynFrmAlias<FMSUB_H, "fmsub.h">;
91def FNMSUB_H : FPFMAH_rrr_frm<OPC_NMSUB, "fnmsub.h">,
92               Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
93def          : FPFMAHDynFrmAlias<FNMSUB_H, "fnmsub.h">;
94def FNMADD_H : FPFMAH_rrr_frm<OPC_NMADD, "fnmadd.h">,
95               Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
96def          : FPFMAHDynFrmAlias<FNMADD_H, "fnmadd.h">;
97
98def FADD_H : FPALUH_rr_frm<0b0000010, "fadd.h">,
99             Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
100def        : FPALUHDynFrmAlias<FADD_H, "fadd.h">;
101def FSUB_H : FPALUH_rr_frm<0b0000110, "fsub.h">,
102             Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
103def        : FPALUHDynFrmAlias<FSUB_H, "fsub.h">;
104def FMUL_H : FPALUH_rr_frm<0b0001010, "fmul.h">,
105             Sched<[WriteFMul16, ReadFMul16, ReadFMul16]>;
106def        : FPALUHDynFrmAlias<FMUL_H, "fmul.h">;
107def FDIV_H : FPALUH_rr_frm<0b0001110, "fdiv.h">,
108             Sched<[WriteFDiv16, ReadFDiv16, ReadFDiv16]>;
109def        : FPALUHDynFrmAlias<FDIV_H, "fdiv.h">;
110
111def FSQRT_H : FPUnaryOp_r_frm<0b0101110, FPR16, FPR16, "fsqrt.h">,
112              Sched<[WriteFSqrt16, ReadFSqrt16]> {
113  let rs2 = 0b00000;
114}
115def         : FPUnaryOpDynFrmAlias<FSQRT_H, "fsqrt.h", FPR16, FPR16>;
116
117def FSGNJ_H  : FPALUH_rr<0b0010010, 0b000, "fsgnj.h">,
118               Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
119def FSGNJN_H : FPALUH_rr<0b0010010, 0b001, "fsgnjn.h">,
120               Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
121def FSGNJX_H : FPALUH_rr<0b0010010, 0b010, "fsgnjx.h">,
122               Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
123def FMIN_H   : FPALUH_rr<0b0010110, 0b000, "fmin.h">,
124               Sched<[WriteFMinMax16, ReadFMinMax16, ReadFMinMax16]>;
125def FMAX_H   : FPALUH_rr<0b0010110, 0b001, "fmax.h">,
126               Sched<[WriteFMinMax16, ReadFMinMax16, ReadFMinMax16]>;
127
128def FCVT_W_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.w.h">,
129               Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]> {
130  let rs2 = 0b00000;
131}
132def          : FPUnaryOpDynFrmAlias<FCVT_W_H, "fcvt.w.h", GPR, FPR16>;
133
134def FCVT_WU_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.wu.h">,
135                Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]> {
136  let rs2 = 0b00001;
137}
138def           : FPUnaryOpDynFrmAlias<FCVT_WU_H, "fcvt.wu.h", GPR, FPR16>;
139
140def FCVT_H_W : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.w">,
141               Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]> {
142  let rs2 = 0b00000;
143}
144def          : FPUnaryOpDynFrmAlias<FCVT_H_W, "fcvt.h.w", FPR16, GPR>;
145
146def FCVT_H_WU : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.wu">,
147                Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]> {
148  let rs2 = 0b00001;
149}
150def           : FPUnaryOpDynFrmAlias<FCVT_H_WU, "fcvt.h.wu", FPR16, GPR>;
151
152def FCVT_H_S : FPUnaryOp_r_frm<0b0100010, FPR16, FPR32, "fcvt.h.s">,
153               Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]> {
154  let rs2 = 0b00000;
155}
156def          : FPUnaryOpDynFrmAlias<FCVT_H_S, "fcvt.h.s", FPR16, FPR32>;
157
158def FCVT_S_H : FPUnaryOp_r<0b0100000, 0b000, FPR32, FPR16, "fcvt.s.h">,
159               Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]> {
160  let rs2 = 0b00010;
161}
162
163def FMV_X_H : FPUnaryOp_r<0b1110010, 0b000, GPR, FPR16, "fmv.x.h">,
164              Sched<[WriteFMovF16ToI16, ReadFMovF16ToI16]> {
165  let rs2 = 0b00000;
166}
167
168def FMV_H_X : FPUnaryOp_r<0b1111010, 0b000, FPR16, GPR, "fmv.h.x">,
169              Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]> {
170  let rs2 = 0b00000;
171}
172
173def FEQ_H : FPCmpH_rr<0b010, "feq.h">;
174def FLT_H : FPCmpH_rr<0b001, "flt.h">;
175def FLE_H : FPCmpH_rr<0b000, "fle.h">;
176
177def FCLASS_H : FPUnaryOp_r<0b1110010, 0b001, GPR, FPR16, "fclass.h">,
178               Sched<[WriteFClass16, ReadFClass16]> {
179  let rs2 = 0b00000;
180}
181} // Predicates = [HasStdExtZfh]
182
183let Predicates = [HasStdExtZfh, IsRV64] in {
184def FCVT_L_H  : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.l.h">,
185                Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]> {
186  let rs2 = 0b00010;
187}
188def           : FPUnaryOpDynFrmAlias<FCVT_L_H, "fcvt.l.h", GPR, FPR16>;
189
190def FCVT_LU_H  : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.lu.h">,
191                 Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]> {
192  let rs2 = 0b00011;
193}
194def            : FPUnaryOpDynFrmAlias<FCVT_LU_H, "fcvt.lu.h", GPR, FPR16>;
195
196def FCVT_H_L : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.l">,
197               Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]> {
198  let rs2 = 0b00010;
199}
200def          : FPUnaryOpDynFrmAlias<FCVT_H_L, "fcvt.h.l", FPR16, GPR>;
201
202def FCVT_H_LU : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.lu">,
203                Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]> {
204  let rs2 = 0b00011;
205}
206def           : FPUnaryOpDynFrmAlias<FCVT_H_LU, "fcvt.h.lu", FPR16, GPR>;
207} // Predicates = [HasStdExtZfh, IsRV64]
208
209let Predicates = [HasStdExtZfh, HasStdExtD] in {
210def FCVT_H_D : FPUnaryOp_r_frm<0b0100010, FPR16, FPR64, "fcvt.h.d">,
211               Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]> {
212  let rs2 = 0b00001;
213}
214def          : FPUnaryOpDynFrmAlias<FCVT_H_D, "fcvt.h.d", FPR16, FPR64>;
215
216def FCVT_D_H : FPUnaryOp_r<0b0100001, 0b000, FPR64, FPR16, "fcvt.d.h">,
217               Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]> {
218  let rs2 = 0b00010;
219}
220} // Predicates = [HasStdExtZfh, HasStdExtD]
221
222//===----------------------------------------------------------------------===//
223// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
224//===----------------------------------------------------------------------===//
225
226let Predicates = [HasStdExtZfh] in {
227def : InstAlias<"flh $rd, (${rs1})",  (FLH FPR16:$rd,  GPR:$rs1, 0), 0>;
228def : InstAlias<"fsh $rs2, (${rs1})", (FSH FPR16:$rs2, GPR:$rs1, 0), 0>;
229
230def : InstAlias<"fmv.h $rd, $rs",  (FSGNJ_H  FPR16:$rd, FPR16:$rs, FPR16:$rs)>;
231def : InstAlias<"fabs.h $rd, $rs", (FSGNJX_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>;
232def : InstAlias<"fneg.h $rd, $rs", (FSGNJN_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>;
233
234// fgt.h/fge.h are recognised by the GNU assembler but the canonical
235// flt.h/fle.h forms will always be printed. Therefore, set a zero weight.
236def : InstAlias<"fgt.h $rd, $rs, $rt",
237                (FLT_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
238def : InstAlias<"fge.h $rd, $rs, $rt",
239                (FLE_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
240
241def PseudoFLH  : PseudoFloatLoad<"flh", FPR16>;
242def PseudoFSH  : PseudoStore<"fsh", FPR16>;
243} // Predicates = [HasStdExtZfh]
244
245//===----------------------------------------------------------------------===//
246// Pseudo-instructions and codegen patterns
247//===----------------------------------------------------------------------===//
248
249/// Generic pattern classes
250class PatFpr16Fpr16<SDPatternOperator OpNode, RVInstR Inst>
251    : Pat<(OpNode FPR16:$rs1, FPR16:$rs2), (Inst $rs1, $rs2)>;
252
253class PatFpr16Fpr16DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst>
254    : Pat<(OpNode FPR16:$rs1, FPR16:$rs2), (Inst $rs1, $rs2, 0b111)>;
255
256let Predicates = [HasStdExtZfh] in {
257
258/// Float constants
259def : Pat<(f16 (fpimm0)), (FMV_H_X X0)>;
260
261/// Float conversion operations
262
263// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so
264// are defined later.
265
266/// Float arithmetic operations
267
268def : PatFpr16Fpr16DynFrm<fadd, FADD_H>;
269def : PatFpr16Fpr16DynFrm<fsub, FSUB_H>;
270def : PatFpr16Fpr16DynFrm<fmul, FMUL_H>;
271def : PatFpr16Fpr16DynFrm<fdiv, FDIV_H>;
272
273def : Pat<(fsqrt FPR16:$rs1), (FSQRT_H FPR16:$rs1, 0b111)>;
274
275def : Pat<(fneg FPR16:$rs1), (FSGNJN_H $rs1, $rs1)>;
276def : Pat<(fabs FPR16:$rs1), (FSGNJX_H $rs1, $rs1)>;
277
278def : PatFpr16Fpr16<fcopysign, FSGNJ_H>;
279def : Pat<(fcopysign FPR16:$rs1, (fneg FPR16:$rs2)), (FSGNJN_H $rs1, $rs2)>;
280def : Pat<(fcopysign FPR16:$rs1, FPR32:$rs2),
281          (FSGNJ_H $rs1, (FCVT_H_S $rs2, 0b111))>;
282def : Pat<(fcopysign FPR32:$rs1, FPR16:$rs2), (FSGNJ_S $rs1, (FCVT_S_H $rs2))>;
283
284// fmadd: rs1 * rs2 + rs3
285def : Pat<(fma FPR16:$rs1, FPR16:$rs2, FPR16:$rs3),
286          (FMADD_H $rs1, $rs2, $rs3, 0b111)>;
287
288// fmsub: rs1 * rs2 - rs3
289def : Pat<(fma FPR16:$rs1, FPR16:$rs2, (fneg FPR16:$rs3)),
290          (FMSUB_H FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, 0b111)>;
291
292// fnmsub: -rs1 * rs2 + rs3
293def : Pat<(fma (fneg FPR16:$rs1), FPR16:$rs2, FPR16:$rs3),
294          (FNMSUB_H FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, 0b111)>;
295
296// fnmadd: -rs1 * rs2 - rs3
297def : Pat<(fma (fneg FPR16:$rs1), FPR16:$rs2, (fneg FPR16:$rs3)),
298          (FNMADD_H FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, 0b111)>;
299
300// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
301// LLVM's fminnum and fmaxnum
302// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
303def : PatFpr16Fpr16<fminnum, FMIN_H>;
304def : PatFpr16Fpr16<fmaxnum, FMAX_H>;
305
306/// Setcc
307
308def : PatFpr16Fpr16<seteq, FEQ_H>;
309def : PatFpr16Fpr16<setoeq, FEQ_H>;
310def : PatFpr16Fpr16<setlt, FLT_H>;
311def : PatFpr16Fpr16<setolt, FLT_H>;
312def : PatFpr16Fpr16<setle, FLE_H>;
313def : PatFpr16Fpr16<setole, FLE_H>;
314
315def Select_FPR16_Using_CC_GPR : SelectCC_rrirr<FPR16, GPR>;
316
317/// Loads
318
319defm : LdPat<load, FLH, f16>;
320
321/// Stores
322
323defm : StPat<store, FSH, FPR16, f16>;
324
325/// Float conversion operations
326
327// f32 -> f16, f16 -> f32
328def : Pat<(fpround FPR32:$rs1), (FCVT_H_S FPR32:$rs1, 0b111)>;
329def : Pat<(fpextend FPR16:$rs1), (FCVT_S_H FPR16:$rs1)>;
330
331// Moves (no conversion)
332def : Pat<(riscv_fmv_h_x GPR:$src), (FMV_H_X GPR:$src)>;
333def : Pat<(riscv_fmv_x_anyexth FPR16:$src), (FMV_X_H FPR16:$src)>;
334} // Predicates = [HasStdExtZfh]
335
336let Predicates = [HasStdExtZfh, IsRV32] in {
337// half->[u]int. Round-to-zero must be used.
338def : Pat<(i32 (fp_to_sint FPR16:$rs1)), (FCVT_W_H $rs1, 0b001)>;
339def : Pat<(i32 (fp_to_uint FPR16:$rs1)), (FCVT_WU_H $rs1, 0b001)>;
340
341// half->int32 with current rounding mode.
342def : Pat<(i32 (lrint FPR16:$rs1)), (FCVT_W_H $rs1, 0b111)>;
343
344// half->int32 rounded to nearest with ties rounded away from zero.
345def : Pat<(i32 (lround FPR16:$rs1)), (FCVT_W_H $rs1, 0b100)>;
346
347// [u]int->half. Match GCC and default to using dynamic rounding mode.
348def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_H_W $rs1, 0b111)>;
349def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_H_WU $rs1, 0b111)>;
350} // Predicates = [HasStdExtZfh, IsRV32]
351
352let Predicates = [HasStdExtZfh, IsRV64] in {
353// Use target specific isd nodes to help us remember the result is sign
354// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
355// duplicated if it has another user that didn't need the sign_extend.
356def : Pat<(riscv_fcvt_w_rv64 FPR16:$rs1),  (FCVT_W_H $rs1, 0b001)>;
357def : Pat<(riscv_fcvt_wu_rv64 FPR16:$rs1), (FCVT_WU_H $rs1, 0b001)>;
358
359// half->[u]int64. Round-to-zero must be used.
360def : Pat<(i64 (fp_to_sint FPR16:$rs1)), (FCVT_L_H $rs1, 0b001)>;
361def : Pat<(i64 (fp_to_uint FPR16:$rs1)), (FCVT_LU_H $rs1, 0b001)>;
362
363// half->int64 with current rounding mode.
364def : Pat<(i64 (lrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>;
365def : Pat<(i64 (llrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>;
366
367// half->int64 rounded to nearest with ties rounded away from zero.
368def : Pat<(i64 (lround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>;
369def : Pat<(i64 (llround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>;
370
371// [u]int->fp. Match GCC and default to using dynamic rounding mode.
372def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_H_W $rs1, 0b111)>;
373def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_H_WU $rs1, 0b111)>;
374def : Pat<(sint_to_fp (i64 GPR:$rs1)), (FCVT_H_L $rs1, 0b111)>;
375def : Pat<(uint_to_fp (i64 GPR:$rs1)), (FCVT_H_LU $rs1, 0b111)>;
376} // Predicates = [HasStdExtZfh, IsRV64]
377
378let Predicates = [HasStdExtZfh, HasStdExtD] in {
379/// Float conversion operations
380// f64 -> f16, f16 -> f64
381def : Pat<(fpround FPR64:$rs1), (FCVT_H_D FPR64:$rs1, 0b111)>;
382def : Pat<(fpextend FPR16:$rs1), (FCVT_D_H FPR16:$rs1)>;
383
384/// Float arithmetic operations
385def : Pat<(fcopysign FPR16:$rs1, FPR64:$rs2),
386          (FSGNJ_H $rs1, (FCVT_H_D $rs2, 0b111))>;
387def : Pat<(fcopysign FPR64:$rs1, FPR16:$rs2), (FSGNJ_D $rs1, (FCVT_D_H $rs2))>;
388}
389