10b57cec5SDimitry Andric//===-- RISCVInstrInfoD.td - RISC-V 'D' instructions -------*- tablegen -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'D', 100b57cec5SDimitry Andric// Double-Precision Floating-Point instruction set extension. 110b57cec5SDimitry Andric// 120b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric// RISC-V specific DAG Nodes. 160b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andricdef SDT_RISCVBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, 190b57cec5SDimitry Andric SDTCisVT<1, i32>, 200b57cec5SDimitry Andric SDTCisSameAs<1, 2>]>; 210b57cec5SDimitry Andricdef SDT_RISCVSplitF64 : SDTypeProfile<2, 1, [SDTCisVT<0, i32>, 220b57cec5SDimitry Andric SDTCisVT<1, i32>, 230b57cec5SDimitry Andric SDTCisVT<2, f64>]>; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andricdef RISCVBuildPairF64 : SDNode<"RISCVISD::BuildPairF64", SDT_RISCVBuildPairF64>; 260b57cec5SDimitry Andricdef RISCVSplitF64 : SDNode<"RISCVISD::SplitF64", SDT_RISCVSplitF64>; 270b57cec5SDimitry Andric 2806c3fb27SDimitry Andricdef AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmINX">; 2906c3fb27SDimitry Andric 300b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 31d56accc7SDimitry Andric// Operand and SDNode transformation definitions. 32d56accc7SDimitry Andric//===----------------------------------------------------------------------===// 33d56accc7SDimitry Andric 34d56accc7SDimitry Andric// Zdinx 35d56accc7SDimitry Andric 36297eecfbSDimitry Andricdef GPRPairAsFPR : AsmOperandClass { 37297eecfbSDimitry Andric let Name = "GPRPairAsFPR"; 38d56accc7SDimitry Andric let ParserMethod = "parseGPRAsFPR"; 391db9f3b2SDimitry Andric let PredicateMethod = "isGPRAsFPR"; 40d56accc7SDimitry Andric let RenderMethod = "addRegOperands"; 41d56accc7SDimitry Andric} 42d56accc7SDimitry Andric 43d56accc7SDimitry Andricdef GPRF64AsFPR : AsmOperandClass { 44d56accc7SDimitry Andric let Name = "GPRF64AsFPR"; 451db9f3b2SDimitry Andric let PredicateMethod = "isGPRAsFPR"; 46d56accc7SDimitry Andric let ParserMethod = "parseGPRAsFPR"; 47d56accc7SDimitry Andric let RenderMethod = "addRegOperands"; 48d56accc7SDimitry Andric} 49d56accc7SDimitry Andric 5006c3fb27SDimitry Andricdef FPR64INX : RegisterOperand<GPR> { 51d56accc7SDimitry Andric let ParserMatchClass = GPRF64AsFPR; 52d56accc7SDimitry Andric let DecoderMethod = "DecodeGPRRegisterClass"; 53d56accc7SDimitry Andric} 54d56accc7SDimitry Andric 55297eecfbSDimitry Andricdef FPR64IN32X : RegisterOperand<GPRPair> { 56297eecfbSDimitry Andric let ParserMatchClass = GPRPairAsFPR; 57d56accc7SDimitry Andric} 58d56accc7SDimitry Andric 5906c3fb27SDimitry Andricdef DExt : ExtInfo<"", "", [HasStdExtD], f64, FPR64, FPR32, FPR64, ?>; 60d56accc7SDimitry Andric 6106c3fb27SDimitry Andricdef ZdinxExt : ExtInfo<"_INX", "RVZfinx", [HasStdExtZdinx, IsRV64], 6206c3fb27SDimitry Andric f64, FPR64INX, FPR32INX, FPR64INX, ?>; 6306c3fb27SDimitry Andricdef Zdinx32Ext : ExtInfo<"_IN32X", "RV32Zdinx", [HasStdExtZdinx, IsRV32], 6406c3fb27SDimitry Andric f64, FPR64IN32X, FPR32INX, FPR64IN32X, ?>; 65d56accc7SDimitry Andric 6606c3fb27SDimitry Andricdefvar DExts = [DExt, ZdinxExt, Zdinx32Ext]; 6706c3fb27SDimitry Andricdefvar DExtsRV64 = [DExt, ZdinxExt]; 68d56accc7SDimitry Andric 69d56accc7SDimitry Andric//===----------------------------------------------------------------------===// 700b57cec5SDimitry Andric// Instructions 710b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 720b57cec5SDimitry Andric 730b57cec5SDimitry Andriclet Predicates = [HasStdExtD] in { 7404eeddc0SDimitry Andricdef FLD : FPLoad_r<0b011, "fld", FPR64, WriteFLD64>; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 770b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 780b57cec5SDimitry Andric// encoding. 7904eeddc0SDimitry Andricdef FSD : FPStore_r<0b011, "fsd", FPR64, WriteFST64>; 80d56accc7SDimitry Andric} // Predicates = [HasStdExtD] 810b57cec5SDimitry Andric 8206c3fb27SDimitry Andricforeach Ext = DExts in { 835f757f3fSDimitry Andric let SchedRW = [WriteFMA64, ReadFMA64, ReadFMA64, ReadFMA64Addend] in { 8406c3fb27SDimitry Andric defm FMADD_D : FPFMA_rrr_frm_m<OPC_MADD, 0b01, "fmadd.d", Ext>; 8506c3fb27SDimitry Andric defm FMSUB_D : FPFMA_rrr_frm_m<OPC_MSUB, 0b01, "fmsub.d", Ext>; 8606c3fb27SDimitry Andric defm FNMSUB_D : FPFMA_rrr_frm_m<OPC_NMSUB, 0b01, "fnmsub.d", Ext>; 8706c3fb27SDimitry Andric defm FNMADD_D : FPFMA_rrr_frm_m<OPC_NMADD, 0b01, "fnmadd.d", Ext>; 880b57cec5SDimitry Andric } 890eae32dcSDimitry Andric 90bdd1243dSDimitry Andric let SchedRW = [WriteFAdd64, ReadFAdd64, ReadFAdd64] in { 9106c3fb27SDimitry Andric defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", Ext, Commutable=1>; 9206c3fb27SDimitry Andric defm FSUB_D : FPALU_rr_frm_m<0b0000101, "fsub.d", Ext>; 93d56accc7SDimitry Andric } 94d56accc7SDimitry Andric let SchedRW = [WriteFMul64, ReadFMul64, ReadFMul64] in 9506c3fb27SDimitry Andric defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", Ext, Commutable=1>; 960eae32dcSDimitry Andric 97d56accc7SDimitry Andric let SchedRW = [WriteFDiv64, ReadFDiv64, ReadFDiv64] in 9806c3fb27SDimitry Andric defm FDIV_D : FPALU_rr_frm_m<0b0001101, "fdiv.d", Ext>; 990eae32dcSDimitry Andric 10006c3fb27SDimitry Andric defm FSQRT_D : FPUnaryOp_r_frm_m<0b0101101, 0b00000, Ext, Ext.PrimaryTy, 10106c3fb27SDimitry Andric Ext.PrimaryTy, "fsqrt.d">, 1020eae32dcSDimitry Andric Sched<[WriteFSqrt64, ReadFSqrt64]>; 1030b57cec5SDimitry Andric 1040eae32dcSDimitry Andric let SchedRW = [WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64], 1050eae32dcSDimitry Andric mayRaiseFPException = 0 in { 10606c3fb27SDimitry Andric defm FSGNJ_D : FPALU_rr_m<0b0010001, 0b000, "fsgnj.d", Ext>; 10706c3fb27SDimitry Andric defm FSGNJN_D : FPALU_rr_m<0b0010001, 0b001, "fsgnjn.d", Ext>; 10806c3fb27SDimitry Andric defm FSGNJX_D : FPALU_rr_m<0b0010001, 0b010, "fsgnjx.d", Ext>; 1090b57cec5SDimitry Andric } 1100eae32dcSDimitry Andric 1110eae32dcSDimitry Andric let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in { 11206c3fb27SDimitry Andric defm FMIN_D : FPALU_rr_m<0b0010101, 0b000, "fmin.d", Ext, Commutable=1>; 11306c3fb27SDimitry Andric defm FMAX_D : FPALU_rr_m<0b0010101, 0b001, "fmax.d", Ext, Commutable=1>; 1140eae32dcSDimitry Andric } 1150eae32dcSDimitry Andric 11606c3fb27SDimitry Andric defm FCVT_S_D : FPUnaryOp_r_frm_m<0b0100000, 0b00001, Ext, Ext.F32Ty, 11706c3fb27SDimitry Andric Ext.PrimaryTy, "fcvt.s.d">, 1180eae32dcSDimitry Andric Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]>; 1190b57cec5SDimitry Andric 1205f757f3fSDimitry Andric defm FCVT_D_S : FPUnaryOp_r_frmlegacy_m<0b0100001, 0b00000, Ext, Ext.PrimaryTy, 12106c3fb27SDimitry Andric Ext.F32Ty, "fcvt.d.s">, 1220eae32dcSDimitry Andric Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>; 1230eae32dcSDimitry Andric 1240eae32dcSDimitry Andric let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in { 12506c3fb27SDimitry Andric defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", Ext, Commutable=1>; 12606c3fb27SDimitry Andric defm FLT_D : FPCmp_rr_m<0b1010001, 0b001, "flt.d", Ext>; 12706c3fb27SDimitry Andric defm FLE_D : FPCmp_rr_m<0b1010001, 0b000, "fle.d", Ext>; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 13006c3fb27SDimitry Andric let mayRaiseFPException = 0 in 13106c3fb27SDimitry Andric defm FCLASS_D : FPUnaryOp_r_m<0b1110001, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy, 13206c3fb27SDimitry Andric "fclass.d">, 1330eae32dcSDimitry Andric Sched<[WriteFClass64, ReadFClass64]>; 1340b57cec5SDimitry Andric 135bdd1243dSDimitry Andric let IsSignExtendingOpW = 1 in 13606c3fb27SDimitry Andric defm FCVT_W_D : FPUnaryOp_r_frm_m<0b1100001, 0b00000, Ext, GPR, Ext.PrimaryTy, 13706c3fb27SDimitry Andric "fcvt.w.d">, 1380eae32dcSDimitry Andric Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>; 1390b57cec5SDimitry Andric 140bdd1243dSDimitry Andric let IsSignExtendingOpW = 1 in 14106c3fb27SDimitry Andric defm FCVT_WU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00001, Ext, GPR, Ext.PrimaryTy, 14206c3fb27SDimitry Andric "fcvt.wu.d">, 1430eae32dcSDimitry Andric Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>; 1440b57cec5SDimitry Andric 1455f757f3fSDimitry Andric defm FCVT_D_W : FPUnaryOp_r_frmlegacy_m<0b1101001, 0b00000, Ext, Ext.PrimaryTy, GPR, 14606c3fb27SDimitry Andric "fcvt.d.w">, 1470eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>; 1480b57cec5SDimitry Andric 1495f757f3fSDimitry Andric defm FCVT_D_WU : FPUnaryOp_r_frmlegacy_m<0b1101001, 0b00001, Ext, Ext.PrimaryTy, GPR, 15006c3fb27SDimitry Andric "fcvt.d.wu">, 1510eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>; 15206c3fb27SDimitry Andric} // foreach Ext = DExts 1530b57cec5SDimitry Andric 15406c3fb27SDimitry Andricforeach Ext = DExtsRV64 in { 15506c3fb27SDimitry Andric defm FCVT_L_D : FPUnaryOp_r_frm_m<0b1100001, 0b00010, Ext, GPR, Ext.PrimaryTy, 15606c3fb27SDimitry Andric "fcvt.l.d", [IsRV64]>, 1570eae32dcSDimitry Andric Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>; 1580b57cec5SDimitry Andric 15906c3fb27SDimitry Andric defm FCVT_LU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00011, Ext, GPR, Ext.PrimaryTy, 16006c3fb27SDimitry Andric "fcvt.lu.d", [IsRV64]>, 1610eae32dcSDimitry Andric Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>; 16206c3fb27SDimitry Andric 16306c3fb27SDimitry Andric defm FCVT_D_L : FPUnaryOp_r_frm_m<0b1101001, 0b00010, Ext, Ext.PrimaryTy, GPR, 16406c3fb27SDimitry Andric "fcvt.d.l", [IsRV64]>, 16506c3fb27SDimitry Andric Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>; 16606c3fb27SDimitry Andric 16706c3fb27SDimitry Andric defm FCVT_D_LU : FPUnaryOp_r_frm_m<0b1101001, 0b00011, Ext, Ext.PrimaryTy, GPR, 16806c3fb27SDimitry Andric "fcvt.d.lu", [IsRV64]>, 16906c3fb27SDimitry Andric Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>; 17006c3fb27SDimitry Andric} // foreach Ext = DExts64 1710b57cec5SDimitry Andric 172d56accc7SDimitry Andriclet Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in 1730eae32dcSDimitry Andricdef FMV_X_D : FPUnaryOp_r<0b1110001, 0b00000, 0b000, GPR, FPR64, "fmv.x.d">, 1740eae32dcSDimitry Andric Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>; 1750b57cec5SDimitry Andric 176d56accc7SDimitry Andriclet Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in 1770eae32dcSDimitry Andricdef FMV_D_X : FPUnaryOp_r<0b1111001, 0b00000, 0b000, FPR64, GPR, "fmv.d.x">, 1780eae32dcSDimitry Andric Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1810b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 1820b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andriclet Predicates = [HasStdExtD] in { 1850b57cec5SDimitry Andricdef : InstAlias<"fld $rd, (${rs1})", (FLD FPR64:$rd, GPR:$rs1, 0), 0>; 1860b57cec5SDimitry Andricdef : InstAlias<"fsd $rs2, (${rs1})", (FSD FPR64:$rs2, GPR:$rs1, 0), 0>; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andricdef : InstAlias<"fmv.d $rd, $rs", (FSGNJ_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; 1890b57cec5SDimitry Andricdef : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; 1900b57cec5SDimitry Andricdef : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric// fgt.d/fge.d are recognised by the GNU assembler but the canonical 1930b57cec5SDimitry Andric// flt.d/fle.d forms will always be printed. Therefore, set a zero weight. 1940b57cec5SDimitry Andricdef : InstAlias<"fgt.d $rd, $rs, $rt", 1950b57cec5SDimitry Andric (FLT_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; 1960b57cec5SDimitry Andricdef : InstAlias<"fge.d $rd, $rs, $rt", 1970b57cec5SDimitry Andric (FLE_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andricdef PseudoFLD : PseudoFloatLoad<"fld", FPR64>; 2000b57cec5SDimitry Andricdef PseudoFSD : PseudoStore<"fsd", FPR64>; 20104eeddc0SDimitry Andriclet usesCustomInserter = 1 in { 20204eeddc0SDimitry Andricdef PseudoQuietFLE_D : PseudoQuietFCMP<FPR64>; 20304eeddc0SDimitry Andricdef PseudoQuietFLT_D : PseudoQuietFCMP<FPR64>; 20404eeddc0SDimitry Andric} 2050b57cec5SDimitry Andric} // Predicates = [HasStdExtD] 2060b57cec5SDimitry Andric 207d56accc7SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 208d56accc7SDimitry Andricdef : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D_INX FPR64INX:$rd, FPR64INX:$rs, FPR64INX:$rs)>; 209d56accc7SDimitry Andricdef : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D_INX FPR64INX:$rd, FPR64INX:$rs, FPR64INX:$rs)>; 210d56accc7SDimitry Andric 211d56accc7SDimitry Andricdef : InstAlias<"fgt.d $rd, $rs, $rt", 212d56accc7SDimitry Andric (FLT_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>; 213d56accc7SDimitry Andricdef : InstAlias<"fge.d $rd, $rs, $rt", 214d56accc7SDimitry Andric (FLE_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>; 21506c3fb27SDimitry Andriclet usesCustomInserter = 1 in { 21606c3fb27SDimitry Andricdef PseudoQuietFLE_D_INX : PseudoQuietFCMP<FPR64INX>; 21706c3fb27SDimitry Andricdef PseudoQuietFLT_D_INX : PseudoQuietFCMP<FPR64INX>; 21806c3fb27SDimitry Andric} 219d56accc7SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 220d56accc7SDimitry Andric 221d56accc7SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 222d56accc7SDimitry Andricdef : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D_IN32X FPR64IN32X:$rd, FPR64IN32X:$rs, FPR64IN32X:$rs)>; 223d56accc7SDimitry Andricdef : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D_IN32X FPR64IN32X:$rd, FPR64IN32X:$rs, FPR64IN32X:$rs)>; 224d56accc7SDimitry Andric 225d56accc7SDimitry Andricdef : InstAlias<"fgt.d $rd, $rs, $rt", 226d56accc7SDimitry Andric (FLT_D_IN32X GPR:$rd, FPR64IN32X:$rt, FPR64IN32X:$rs), 0>; 227d56accc7SDimitry Andricdef : InstAlias<"fge.d $rd, $rs, $rt", 228d56accc7SDimitry Andric (FLE_D_IN32X GPR:$rd, FPR64IN32X:$rt, FPR64IN32X:$rs), 0>; 22906c3fb27SDimitry Andriclet usesCustomInserter = 1 in { 23006c3fb27SDimitry Andricdef PseudoQuietFLE_D_IN32X : PseudoQuietFCMP<FPR64IN32X>; 23106c3fb27SDimitry Andricdef PseudoQuietFLT_D_IN32X : PseudoQuietFCMP<FPR64IN32X>; 23206c3fb27SDimitry Andric} 233d56accc7SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 234d56accc7SDimitry Andric 2350b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2360b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 2370b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andriclet Predicates = [HasStdExtD] in { 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric/// Float conversion operations 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric// f64 -> f32, f32 -> f64 24406c3fb27SDimitry Andricdef : Pat<(any_fpround FPR64:$rs1), (FCVT_S_D FPR64:$rs1, FRM_DYN)>; 2455f757f3fSDimitry Andricdef : Pat<(any_fpextend FPR32:$rs1), (FCVT_D_S FPR32:$rs1, FRM_RNE)>; 24606c3fb27SDimitry Andric} // Predicates = [HasStdExtD] 24706c3fb27SDimitry Andric 24806c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 24906c3fb27SDimitry Andric/// Float conversion operations 25006c3fb27SDimitry Andric 25106c3fb27SDimitry Andric// f64 -> f32, f32 -> f64 25206c3fb27SDimitry Andricdef : Pat<(any_fpround FPR64INX:$rs1), (FCVT_S_D_INX FPR64INX:$rs1, FRM_DYN)>; 2535f757f3fSDimitry Andricdef : Pat<(any_fpextend FPR32INX:$rs1), (FCVT_D_S_INX FPR32INX:$rs1, FRM_RNE)>; 25406c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 25506c3fb27SDimitry Andric 25606c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 25706c3fb27SDimitry Andric/// Float conversion operations 25806c3fb27SDimitry Andric 25906c3fb27SDimitry Andric// f64 -> f32, f32 -> f64 26006c3fb27SDimitry Andricdef : Pat<(any_fpround FPR64IN32X:$rs1), (FCVT_S_D_IN32X FPR64IN32X:$rs1, FRM_DYN)>; 2615f757f3fSDimitry Andricdef : Pat<(any_fpextend FPR32INX:$rs1), (FCVT_D_S_IN32X FPR32INX:$rs1, FRM_RNE)>; 26206c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric// [u]int<->double conversion patterns must be gated on IsRV32 or IsRV64, so 2650b57cec5SDimitry Andric// are defined later. 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric/// Float arithmetic operations 2680b57cec5SDimitry Andric 26906c3fb27SDimitry Andricforeach Ext = DExts in { 27006c3fb27SDimitry Andric defm : PatFprFprDynFrm_m<any_fadd, FADD_D, Ext>; 27106c3fb27SDimitry Andric defm : PatFprFprDynFrm_m<any_fsub, FSUB_D, Ext>; 27206c3fb27SDimitry Andric defm : PatFprFprDynFrm_m<any_fmul, FMUL_D, Ext>; 27306c3fb27SDimitry Andric defm : PatFprFprDynFrm_m<any_fdiv, FDIV_D, Ext>; 27406c3fb27SDimitry Andric} 2750b57cec5SDimitry Andric 27606c3fb27SDimitry Andriclet Predicates = [HasStdExtD] in { 27706c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR64:$rs1), (FSQRT_D FPR64:$rs1, FRM_DYN)>; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andricdef : Pat<(fneg FPR64:$rs1), (FSGNJN_D $rs1, $rs1)>; 2800b57cec5SDimitry Andricdef : Pat<(fabs FPR64:$rs1), (FSGNJX_D $rs1, $rs1)>; 2810b57cec5SDimitry Andric 2825f757f3fSDimitry Andricdef : Pat<(riscv_fclass FPR64:$rs1), (FCLASS_D $rs1)>; 28306c3fb27SDimitry Andric 28406c3fb27SDimitry Andricdef : PatFprFpr<fcopysign, FSGNJ_D, FPR64, f64>; 2850b57cec5SDimitry Andricdef : Pat<(fcopysign FPR64:$rs1, (fneg FPR64:$rs2)), (FSGNJN_D $rs1, $rs2)>; 2865f757f3fSDimitry Andricdef : Pat<(fcopysign FPR64:$rs1, FPR32:$rs2), (FSGNJ_D $rs1, (FCVT_D_S $rs2, 2875f757f3fSDimitry Andric FRM_RNE))>; 2882b2a17f4SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, FPR64:$rs2), (FSGNJ_S $rs1, (FCVT_S_D $rs2, 28906c3fb27SDimitry Andric FRM_DYN))>; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3 2920eae32dcSDimitry Andricdef : Pat<(any_fma FPR64:$rs1, FPR64:$rs2, FPR64:$rs3), 29306c3fb27SDimitry Andric (FMADD_D $rs1, $rs2, $rs3, FRM_DYN)>; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3 2960eae32dcSDimitry Andricdef : Pat<(any_fma FPR64:$rs1, FPR64:$rs2, (fneg FPR64:$rs3)), 29706c3fb27SDimitry Andric (FMSUB_D FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, FRM_DYN)>; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3 3000eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR64:$rs1), FPR64:$rs2, FPR64:$rs3), 30106c3fb27SDimitry Andric (FNMSUB_D FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, FRM_DYN)>; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3 3040eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR64:$rs1), FPR64:$rs2, (fneg FPR64:$rs3)), 30506c3fb27SDimitry Andric (FNMADD_D FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, FRM_DYN)>; 3060b57cec5SDimitry Andric 30781ad6265SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA) 30881ad6265SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR64:$rs1, FPR64:$rs2, FPR64:$rs3)), 30906c3fb27SDimitry Andric (FNMADD_D FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, FRM_DYN)>; 31006c3fb27SDimitry Andric} // Predicates = [HasStdExtD] 31106c3fb27SDimitry Andric 31206c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 31306c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR64INX:$rs1), (FSQRT_D_INX FPR64INX:$rs1, FRM_DYN)>; 31406c3fb27SDimitry Andric 31506c3fb27SDimitry Andricdef : Pat<(fneg FPR64INX:$rs1), (FSGNJN_D_INX $rs1, $rs1)>; 31606c3fb27SDimitry Andricdef : Pat<(fabs FPR64INX:$rs1), (FSGNJX_D_INX $rs1, $rs1)>; 31706c3fb27SDimitry Andric 3185f757f3fSDimitry Andricdef : Pat<(riscv_fclass FPR64INX:$rs1), (FCLASS_D_INX $rs1)>; 31906c3fb27SDimitry Andric 32006c3fb27SDimitry Andricdef : PatFprFpr<fcopysign, FSGNJ_D_INX, FPR64INX, f64>; 32106c3fb27SDimitry Andricdef : Pat<(fcopysign FPR64INX:$rs1, (fneg FPR64INX:$rs2)), 32206c3fb27SDimitry Andric (FSGNJN_D_INX $rs1, $rs2)>; 32306c3fb27SDimitry Andricdef : Pat<(fcopysign FPR64INX:$rs1, FPR32INX:$rs2), 3245f757f3fSDimitry Andric (FSGNJ_D_INX $rs1, (FCVT_D_S_INX $rs2, FRM_RNE))>; 32506c3fb27SDimitry Andricdef : Pat<(fcopysign FPR32INX:$rs1, FPR64INX:$rs2), 32606c3fb27SDimitry Andric (FSGNJ_S_INX $rs1, (FCVT_S_D_INX $rs2, FRM_DYN))>; 32706c3fb27SDimitry Andric 32806c3fb27SDimitry Andric// fmadd: rs1 * rs2 + rs3 32906c3fb27SDimitry Andricdef : Pat<(any_fma FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3), 33006c3fb27SDimitry Andric (FMADD_D_INX $rs1, $rs2, $rs3, FRM_DYN)>; 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric// fmsub: rs1 * rs2 - rs3 33306c3fb27SDimitry Andricdef : Pat<(any_fma FPR64INX:$rs1, FPR64INX:$rs2, (fneg FPR64INX:$rs3)), 33406c3fb27SDimitry Andric (FMSUB_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>; 33506c3fb27SDimitry Andric 33606c3fb27SDimitry Andric// fnmsub: -rs1 * rs2 + rs3 33706c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR64INX:$rs1), FPR64INX:$rs2, FPR64INX:$rs3), 33806c3fb27SDimitry Andric (FNMSUB_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>; 33906c3fb27SDimitry Andric 34006c3fb27SDimitry Andric// fnmadd: -rs1 * rs2 - rs3 34106c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR64INX:$rs1), FPR64INX:$rs2, (fneg FPR64INX:$rs3)), 34206c3fb27SDimitry Andric (FNMADD_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>; 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA) 34506c3fb27SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3)), 34606c3fb27SDimitry Andric (FNMADD_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>; 34706c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 35006c3fb27SDimitry Andricdef : Pat<(any_fsqrt FPR64IN32X:$rs1), (FSQRT_D_IN32X FPR64IN32X:$rs1, FRM_DYN)>; 35106c3fb27SDimitry Andric 35206c3fb27SDimitry Andricdef : Pat<(fneg FPR64IN32X:$rs1), (FSGNJN_D_IN32X $rs1, $rs1)>; 35306c3fb27SDimitry Andricdef : Pat<(fabs FPR64IN32X:$rs1), (FSGNJX_D_IN32X $rs1, $rs1)>; 35406c3fb27SDimitry Andric 3555f757f3fSDimitry Andricdef : Pat<(riscv_fclass FPR64IN32X:$rs1), (FCLASS_D_IN32X $rs1)>; 35606c3fb27SDimitry Andric 35706c3fb27SDimitry Andricdef : PatFprFpr<fcopysign, FSGNJ_D_IN32X, FPR64IN32X, f64>; 35806c3fb27SDimitry Andricdef : Pat<(fcopysign FPR64IN32X:$rs1, (fneg FPR64IN32X:$rs2)), 35906c3fb27SDimitry Andric (FSGNJN_D_IN32X $rs1, $rs2)>; 36006c3fb27SDimitry Andricdef : Pat<(fcopysign FPR64IN32X:$rs1, FPR32INX:$rs2), 3615f757f3fSDimitry Andric (FSGNJ_D_IN32X $rs1, (FCVT_D_S_INX $rs2, FRM_RNE))>; 36206c3fb27SDimitry Andricdef : Pat<(fcopysign FPR32INX:$rs1, FPR64IN32X:$rs2), 36306c3fb27SDimitry Andric (FSGNJ_S_INX $rs1, (FCVT_S_D_IN32X $rs2, FRM_DYN))>; 36406c3fb27SDimitry Andric 36506c3fb27SDimitry Andric// fmadd: rs1 * rs2 + rs3 36606c3fb27SDimitry Andricdef : Pat<(any_fma FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3), 36706c3fb27SDimitry Andric (FMADD_D_IN32X $rs1, $rs2, $rs3, FRM_DYN)>; 36806c3fb27SDimitry Andric 36906c3fb27SDimitry Andric// fmsub: rs1 * rs2 - rs3 37006c3fb27SDimitry Andricdef : Pat<(any_fma FPR64IN32X:$rs1, FPR64IN32X:$rs2, (fneg FPR64IN32X:$rs3)), 37106c3fb27SDimitry Andric (FMSUB_D_IN32X FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3, FRM_DYN)>; 37206c3fb27SDimitry Andric 37306c3fb27SDimitry Andric// fnmsub: -rs1 * rs2 + rs3 37406c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR64IN32X:$rs1), FPR64IN32X:$rs2, FPR64IN32X:$rs3), 37506c3fb27SDimitry Andric (FNMSUB_D_IN32X FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3, FRM_DYN)>; 37606c3fb27SDimitry Andric 37706c3fb27SDimitry Andric// fnmadd: -rs1 * rs2 - rs3 37806c3fb27SDimitry Andricdef : Pat<(any_fma (fneg FPR64IN32X:$rs1), FPR64IN32X:$rs2, (fneg FPR64IN32X:$rs3)), 37906c3fb27SDimitry Andric (FNMADD_D_IN32X FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3, FRM_DYN)>; 38006c3fb27SDimitry Andric 38106c3fb27SDimitry Andric// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA) 38206c3fb27SDimitry Andricdef : Pat<(fneg (any_fma_nsz FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3)), 38306c3fb27SDimitry Andric (FNMADD_D_IN32X FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3, FRM_DYN)>; 38406c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 38581ad6265SDimitry Andric 386fe6060f1SDimitry Andric// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches 387fe6060f1SDimitry Andric// LLVM's fminnum and fmaxnum. 3880b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>. 38906c3fb27SDimitry Andricforeach Ext = DExts in { 39006c3fb27SDimitry Andric defm : PatFprFpr_m<fminnum, FMIN_D, Ext>; 39106c3fb27SDimitry Andric defm : PatFprFpr_m<fmaxnum, FMAX_D, Ext>; 39206c3fb27SDimitry Andric defm : PatFprFpr_m<riscv_fmin, FMIN_D, Ext>; 39306c3fb27SDimitry Andric defm : PatFprFpr_m<riscv_fmax, FMAX_D, Ext>; 39406c3fb27SDimitry Andric} 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric/// Setcc 39704eeddc0SDimitry Andric// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for 39804eeddc0SDimitry Andric// strict versions of those. 3990b57cec5SDimitry Andric 40004eeddc0SDimitry Andric// Match non-signaling FEQ_D 40106c3fb27SDimitry Andricforeach Ext = DExts in { 4025f757f3fSDimitry Andric defm : PatSetCC_m<any_fsetcc, SETEQ, FEQ_D, Ext>; 4035f757f3fSDimitry Andric defm : PatSetCC_m<any_fsetcc, SETOEQ, FEQ_D, Ext>; 4045f757f3fSDimitry Andric defm : PatSetCC_m<strict_fsetcc, SETLT, PseudoQuietFLT_D, Ext>; 4055f757f3fSDimitry Andric defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_D, Ext>; 4065f757f3fSDimitry Andric defm : PatSetCC_m<strict_fsetcc, SETLE, PseudoQuietFLE_D, Ext>; 4075f757f3fSDimitry Andric defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_D, Ext>; 40806c3fb27SDimitry Andric} 40904eeddc0SDimitry Andric 41006c3fb27SDimitry Andriclet Predicates = [HasStdExtD] in { 41104eeddc0SDimitry Andric// Match signaling FEQ_D 41206c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64:$rs1, FPR64:$rs2, SETEQ)), 413*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D $rs1, $rs2)), 414*0fca6ea1SDimitry Andric (XLenVT (FLE_D $rs2, $rs1)))>; 41506c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64:$rs1, FPR64:$rs2, SETOEQ)), 416*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D $rs1, $rs2)), 417*0fca6ea1SDimitry Andric (XLenVT (FLE_D $rs2, $rs1)))>; 41804eeddc0SDimitry Andric// If both operands are the same, use a single FLE. 41906c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64:$rs1, FPR64:$rs1, SETEQ)), 42004eeddc0SDimitry Andric (FLE_D $rs1, $rs1)>; 42106c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64:$rs1, FPR64:$rs1, SETOEQ)), 42204eeddc0SDimitry Andric (FLE_D $rs1, $rs1)>; 42304eeddc0SDimitry Andric 42406c3fb27SDimitry Andricdef : PatSetCC<FPR64, any_fsetccs, SETLT, FLT_D, f64>; 42506c3fb27SDimitry Andricdef : PatSetCC<FPR64, any_fsetccs, SETOLT, FLT_D, f64>; 42606c3fb27SDimitry Andricdef : PatSetCC<FPR64, any_fsetccs, SETLE, FLE_D, f64>; 42706c3fb27SDimitry Andricdef : PatSetCC<FPR64, any_fsetccs, SETOLE, FLE_D, f64>; 42806c3fb27SDimitry Andric} // Predicates = [HasStdExtD] 4290b57cec5SDimitry Andric 43006c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 43106c3fb27SDimitry Andric// Match signaling FEQ_D 43206c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs (f64 FPR64INX:$rs1), FPR64INX:$rs2, SETEQ)), 433*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D_INX $rs1, $rs2)), 434*0fca6ea1SDimitry Andric (XLenVT (FLE_D_INX $rs2, $rs1)))>; 43506c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs (f64 FPR64INX:$rs1), FPR64INX:$rs2, SETOEQ)), 436*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D_INX $rs1, $rs2)), 437*0fca6ea1SDimitry Andric (XLenVT (FLE_D_INX $rs2, $rs1)))>; 43806c3fb27SDimitry Andric// If both operands are the same, use a single FLE. 43906c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs (f64 FPR64INX:$rs1), FPR64INX:$rs1, SETEQ)), 44006c3fb27SDimitry Andric (FLE_D_INX $rs1, $rs1)>; 44106c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs (f64 FPR64INX:$rs1), FPR64INX:$rs1, SETOEQ)), 44206c3fb27SDimitry Andric (FLE_D_INX $rs1, $rs1)>; 443bdd1243dSDimitry Andric 44406c3fb27SDimitry Andricdef : PatSetCC<FPR64INX, any_fsetccs, SETLT, FLT_D_INX, f64>; 44506c3fb27SDimitry Andricdef : PatSetCC<FPR64INX, any_fsetccs, SETOLT, FLT_D_INX, f64>; 44606c3fb27SDimitry Andricdef : PatSetCC<FPR64INX, any_fsetccs, SETLE, FLE_D_INX, f64>; 44706c3fb27SDimitry Andricdef : PatSetCC<FPR64INX, any_fsetccs, SETOLE, FLE_D_INX, f64>; 44806c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 44906c3fb27SDimitry Andric 45006c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 45106c3fb27SDimitry Andric// Match signaling FEQ_D 45206c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64IN32X:$rs1, FPR64IN32X:$rs2, SETEQ)), 453*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D_IN32X $rs1, $rs2)), 454*0fca6ea1SDimitry Andric (XLenVT (FLE_D_IN32X $rs2, $rs1)))>; 45506c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64IN32X:$rs1, FPR64IN32X:$rs2, SETOEQ)), 456*0fca6ea1SDimitry Andric (AND (XLenVT (FLE_D_IN32X $rs1, $rs2)), 457*0fca6ea1SDimitry Andric (XLenVT (FLE_D_IN32X $rs2, $rs1)))>; 45806c3fb27SDimitry Andric// If both operands are the same, use a single FLE. 45906c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64IN32X:$rs1, FPR64IN32X:$rs1, SETEQ)), 46006c3fb27SDimitry Andric (FLE_D_IN32X $rs1, $rs1)>; 46106c3fb27SDimitry Andricdef : Pat<(XLenVT (strict_fsetccs FPR64IN32X:$rs1, FPR64IN32X:$rs1, SETOEQ)), 46206c3fb27SDimitry Andric (FLE_D_IN32X $rs1, $rs1)>; 46306c3fb27SDimitry Andric 46406c3fb27SDimitry Andricdef : PatSetCC<FPR64IN32X, any_fsetccs, SETLT, FLT_D_IN32X, f64>; 46506c3fb27SDimitry Andricdef : PatSetCC<FPR64IN32X, any_fsetccs, SETOLT, FLT_D_IN32X, f64>; 46606c3fb27SDimitry Andricdef : PatSetCC<FPR64IN32X, any_fsetccs, SETLE, FLE_D_IN32X, f64>; 46706c3fb27SDimitry Andricdef : PatSetCC<FPR64IN32X, any_fsetccs, SETOLE, FLE_D_IN32X, f64>; 46806c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 46906c3fb27SDimitry Andric 47006c3fb27SDimitry Andriclet Predicates = [HasStdExtD] in { 47106c3fb27SDimitry Andricdefm Select_FPR64 : SelectCC_GPR_rrirr<FPR64, f64>; 47206c3fb27SDimitry Andric 47306c3fb27SDimitry Andricdef PseudoFROUND_D : PseudoFROUND<FPR64, f64>; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric/// Loads 4760b57cec5SDimitry Andric 47706c3fb27SDimitry Andricdef : LdPat<load, FLD, f64>; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric/// Stores 4800b57cec5SDimitry Andric 48106c3fb27SDimitry Andricdef : StPat<store, FSD, FPR64, f64>; 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric/// Pseudo-instructions needed for the soft-float ABI with RV32D 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric// Moves two GPRs to an FPR. 4860b57cec5SDimitry Andriclet usesCustomInserter = 1 in 4870b57cec5SDimitry Andricdef BuildPairF64Pseudo 4880b57cec5SDimitry Andric : Pseudo<(outs FPR64:$dst), (ins GPR:$src1, GPR:$src2), 4890b57cec5SDimitry Andric [(set FPR64:$dst, (RISCVBuildPairF64 GPR:$src1, GPR:$src2))]>; 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric// Moves an FPR to two GPRs. 4920b57cec5SDimitry Andriclet usesCustomInserter = 1 in 4930b57cec5SDimitry Andricdef SplitF64Pseudo 4940b57cec5SDimitry Andric : Pseudo<(outs GPR:$dst1, GPR:$dst2), (ins FPR64:$src), 4950b57cec5SDimitry Andric [(set GPR:$dst1, GPR:$dst2, (RISCVSplitF64 FPR64:$src))]>; 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric} // Predicates = [HasStdExtD] 4980b57cec5SDimitry Andric 49906c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 50006c3fb27SDimitry Andricdefm Select_FPR64INX : SelectCC_GPR_rrirr<FPR64INX, f64>; 50106c3fb27SDimitry Andric 50206c3fb27SDimitry Andricdef PseudoFROUND_D_INX : PseudoFROUND<FPR64INX, f64>; 50306c3fb27SDimitry Andric 50406c3fb27SDimitry Andric/// Loads 50506c3fb27SDimitry Andricdef : LdPat<load, LD, f64>; 50606c3fb27SDimitry Andric 50706c3fb27SDimitry Andric/// Stores 50806c3fb27SDimitry Andricdef : StPat<store, SD, GPR, f64>; 50906c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 51006c3fb27SDimitry Andric 51106c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 51206c3fb27SDimitry Andricdefm Select_FPR64IN32X : SelectCC_GPR_rrirr<FPR64IN32X, f64>; 51306c3fb27SDimitry Andric 51406c3fb27SDimitry Andricdef PseudoFROUND_D_IN32X : PseudoFROUND<FPR64IN32X, f64>; 51506c3fb27SDimitry Andric 51606c3fb27SDimitry Andric/// Loads 51706c3fb27SDimitry Andriclet isCall = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 1 in 518297eecfbSDimitry Andricdef PseudoRV32ZdinxLD : Pseudo<(outs GPRPair:$dst), (ins GPR:$rs1, simm12:$imm12), []>; 51906c3fb27SDimitry Andricdef : Pat<(f64 (load (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12))), 52006c3fb27SDimitry Andric (PseudoRV32ZdinxLD GPR:$rs1, simm12:$imm12)>; 52106c3fb27SDimitry Andric 52206c3fb27SDimitry Andric/// Stores 52306c3fb27SDimitry Andriclet isCall = 0, mayLoad = 0, mayStore = 1, Size = 8, isCodeGenOnly = 1 in 524297eecfbSDimitry Andricdef PseudoRV32ZdinxSD : Pseudo<(outs), (ins GPRPair:$rs2, GPRNoX0:$rs1, simm12:$imm12), []>; 525297eecfbSDimitry Andricdef : Pat<(store (f64 GPRPair:$rs2), (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12)), 526297eecfbSDimitry Andric (PseudoRV32ZdinxSD GPRPair:$rs2, GPR:$rs1, simm12:$imm12)>; 52706c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 52806c3fb27SDimitry Andric 5295f757f3fSDimitry Andriclet Predicates = [HasStdExtD] in { 5305ffd83dbSDimitry Andric 5310b57cec5SDimitry Andric// double->[u]int. Round-to-zero must be used. 53206c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR64:$rs1)), (FCVT_W_D FPR64:$rs1, FRM_RTZ)>; 53306c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR64:$rs1)), (FCVT_WU_D FPR64:$rs1, FRM_RTZ)>; 534fe6060f1SDimitry Andric 535349cc55cSDimitry Andric// Saturating double->[u]int32. 53604eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR64:$rs1, timm:$frm)), (FCVT_W_D $rs1, timm:$frm)>; 53704eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR64:$rs1, timm:$frm)), (FCVT_WU_D $rs1, timm:$frm)>; 538349cc55cSDimitry Andric 539fe6060f1SDimitry Andric// float->int32 with current rounding mode. 54006c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR64:$rs1)), (FCVT_W_D $rs1, FRM_DYN)>; 541fe6060f1SDimitry Andric 542fe6060f1SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero. 54306c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR64:$rs1)), (FCVT_W_D $rs1, FRM_RMM)>; 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric// [u]int->double. 5465f757f3fSDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_D_W GPR:$rs1, FRM_RNE)>; 5475f757f3fSDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_D_WU GPR:$rs1, FRM_RNE)>; 5485f757f3fSDimitry Andric} // Predicates = [HasStdExtD] 5490b57cec5SDimitry Andric 55006c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV32] in { 5515ffd83dbSDimitry Andric 55206c3fb27SDimitry Andric// double->[u]int. Round-to-zero must be used. 55306c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR64IN32X:$rs1)), (FCVT_W_D_IN32X FPR64IN32X:$rs1, FRM_RTZ)>; 55406c3fb27SDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR64IN32X:$rs1)), (FCVT_WU_D_IN32X FPR64IN32X:$rs1, FRM_RTZ)>; 55506c3fb27SDimitry Andric 55606c3fb27SDimitry Andric// Saturating double->[u]int32. 55706c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR64IN32X:$rs1, timm:$frm)), (FCVT_W_D_IN32X $rs1, timm:$frm)>; 55806c3fb27SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR64IN32X:$rs1, timm:$frm)), (FCVT_WU_D_IN32X $rs1, timm:$frm)>; 55906c3fb27SDimitry Andric 56006c3fb27SDimitry Andric// float->int32 with current rounding mode. 56106c3fb27SDimitry Andricdef : Pat<(i32 (any_lrint FPR64IN32X:$rs1)), (FCVT_W_D_IN32X $rs1, FRM_DYN)>; 56206c3fb27SDimitry Andric 56306c3fb27SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero. 56406c3fb27SDimitry Andricdef : Pat<(i32 (any_lround FPR64IN32X:$rs1)), (FCVT_W_D_IN32X $rs1, FRM_RMM)>; 56506c3fb27SDimitry Andric 56606c3fb27SDimitry Andric// [u]int->double. 5675f757f3fSDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_D_W_IN32X GPR:$rs1, FRM_RNE)>; 5685f757f3fSDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_D_WU_IN32X GPR:$rs1, FRM_RNE)>; 56906c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV32] 57006c3fb27SDimitry Andric 57106c3fb27SDimitry Andriclet Predicates = [HasStdExtD, IsRV64] in { 5725ffd83dbSDimitry Andric 573e8d8bef9SDimitry Andric// Moves (no conversion) 574fe6060f1SDimitry Andricdef : Pat<(bitconvert (i64 GPR:$rs1)), (FMV_D_X GPR:$rs1)>; 575fe6060f1SDimitry Andricdef : Pat<(i64 (bitconvert FPR64:$rs1)), (FMV_X_D FPR64:$rs1)>; 5760b57cec5SDimitry Andric 577fe6060f1SDimitry Andric// Use target specific isd nodes to help us remember the result is sign 578fe6060f1SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be 579fe6060f1SDimitry Andric// duplicated if it has another user that didn't need the sign_extend. 58004eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR64:$rs1, timm:$frm), (FCVT_W_D $rs1, timm:$frm)>; 58104eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR64:$rs1, timm:$frm), (FCVT_WU_D $rs1, timm:$frm)>; 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric// [u]int32->fp 5845f757f3fSDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_D_W $rs1, FRM_RNE)>; 5855f757f3fSDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_D_WU $rs1, FRM_RNE)>; 5860b57cec5SDimitry Andric 587349cc55cSDimitry Andric// Saturating double->[u]int64. 58804eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR64:$rs1, timm:$frm)), (FCVT_L_D $rs1, timm:$frm)>; 58904eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR64:$rs1, timm:$frm)), (FCVT_LU_D $rs1, timm:$frm)>; 590349cc55cSDimitry Andric 591fe6060f1SDimitry Andric// double->[u]int64. Round-to-zero must be used. 59206c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR64:$rs1)), (FCVT_L_D FPR64:$rs1, FRM_RTZ)>; 59306c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR64:$rs1)), (FCVT_LU_D FPR64:$rs1, FRM_RTZ)>; 594fe6060f1SDimitry Andric 595fe6060f1SDimitry Andric// double->int64 with current rounding mode. 59606c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR64:$rs1)), (FCVT_L_D $rs1, FRM_DYN)>; 59706c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR64:$rs1)), (FCVT_L_D $rs1, FRM_DYN)>; 598fe6060f1SDimitry Andric 599fe6060f1SDimitry Andric// double->int64 rounded to nearest with ties rounded away from zero. 60006c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR64:$rs1)), (FCVT_L_D $rs1, FRM_RMM)>; 60106c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR64:$rs1)), (FCVT_L_D $rs1, FRM_RMM)>; 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric// [u]int64->fp. Match GCC and default to using dynamic rounding mode. 60406c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_D_L GPR:$rs1, FRM_DYN)>; 60506c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_D_LU GPR:$rs1, FRM_DYN)>; 6060b57cec5SDimitry Andric} // Predicates = [HasStdExtD, IsRV64] 60706c3fb27SDimitry Andric 60806c3fb27SDimitry Andriclet Predicates = [HasStdExtZdinx, IsRV64] in { 60906c3fb27SDimitry Andric 61006c3fb27SDimitry Andric// Moves (no conversion) 61106c3fb27SDimitry Andricdef : Pat<(f64 (bitconvert (i64 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPR)>; 61206c3fb27SDimitry Andricdef : Pat<(i64 (bitconvert (f64 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPR)>; 61306c3fb27SDimitry Andric 61406c3fb27SDimitry Andric// Use target specific isd nodes to help us remember the result is sign 61506c3fb27SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be 61606c3fb27SDimitry Andric// duplicated if it has another user that didn't need the sign_extend. 61706c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR64INX:$rs1, timm:$frm), (FCVT_W_D_INX $rs1, timm:$frm)>; 61806c3fb27SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR64INX:$rs1, timm:$frm), (FCVT_WU_D_INX $rs1, timm:$frm)>; 61906c3fb27SDimitry Andric 62006c3fb27SDimitry Andric// [u]int32->fp 6215f757f3fSDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_D_W_INX $rs1, FRM_RNE)>; 6225f757f3fSDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_D_WU_INX $rs1, FRM_RNE)>; 62306c3fb27SDimitry Andric 62406c3fb27SDimitry Andric// Saturating double->[u]int64. 62506c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR64INX:$rs1, timm:$frm)), (FCVT_L_D_INX $rs1, timm:$frm)>; 62606c3fb27SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR64INX:$rs1, timm:$frm)), (FCVT_LU_D_INX $rs1, timm:$frm)>; 62706c3fb27SDimitry Andric 62806c3fb27SDimitry Andric// double->[u]int64. Round-to-zero must be used. 62906c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR64INX:$rs1)), (FCVT_L_D_INX FPR64INX:$rs1, FRM_RTZ)>; 63006c3fb27SDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR64INX:$rs1)), (FCVT_LU_D_INX FPR64INX:$rs1, FRM_RTZ)>; 63106c3fb27SDimitry Andric 63206c3fb27SDimitry Andric// double->int64 with current rounding mode. 63306c3fb27SDimitry Andricdef : Pat<(i64 (any_lrint FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_DYN)>; 63406c3fb27SDimitry Andricdef : Pat<(i64 (any_llrint FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_DYN)>; 63506c3fb27SDimitry Andric 63606c3fb27SDimitry Andric// double->int64 rounded to nearest with ties rounded away from zero. 63706c3fb27SDimitry Andricdef : Pat<(i64 (any_lround FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_RMM)>; 63806c3fb27SDimitry Andricdef : Pat<(i64 (any_llround FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_RMM)>; 63906c3fb27SDimitry Andric 64006c3fb27SDimitry Andric// [u]int64->fp. Match GCC and default to using dynamic rounding mode. 64106c3fb27SDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_D_L_INX GPR:$rs1, FRM_DYN)>; 64206c3fb27SDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_D_LU_INX GPR:$rs1, FRM_DYN)>; 64306c3fb27SDimitry Andric} // Predicates = [HasStdExtZdinx, IsRV64] 644