diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 780bc6cf38eb0..82a3458ec487a 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -712,16 +712,16 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { } case ISD::ConstantFP: { const APFloat &APF = cast(Node)->getValueAPF(); - // td can handle +0.0 already. - if (APF.isPosZero()) - break; - // Special case: a 64 bit -0.0 uses more instructions than fmv + fneg. - if (APF.isNegZero() && VT == MVT::f64) - break; - assert(VT.bitsLE(Subtarget->getXLenVT()) && - "Cannot create a 64 bit floating-point immediate value for rv32"); - SDValue Imm = selectImm(CurDAG, DL, XLenVT, - APF.bitcastToAPInt().getSExtValue(), *Subtarget); + bool NegZeroF64 = APF.isNegZero() && VT == MVT::f64; + SDValue Imm; + // For +0.0 or f64 -0.0 we need to start from X0. For all others, we will + // create an integer immediate. + if (APF.isPosZero() || NegZeroF64) + Imm = CurDAG->getRegister(RISCV::X0, XLenVT); + else + Imm = selectImm(CurDAG, DL, XLenVT, APF.bitcastToAPInt().getSExtValue(), + *Subtarget); + unsigned Opc; switch (VT.SimpleTy) { default: @@ -733,10 +733,21 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { Opc = RISCV::FMV_W_X; break; case MVT::f64: - Opc = RISCV::FMV_D_X; + // For RV32, we can't move from a GPR, we need to convert instead. This + // should only happen for +0.0 and -0.0. + assert((Subtarget->is64Bit() || APF.isZero()) && "Unexpected constant"); + Opc = Subtarget->is64Bit() ? RISCV::FMV_D_X : RISCV::FCVT_D_W; break; } - ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, Imm)); + + SDNode *Res = CurDAG->getMachineNode(Opc, DL, VT, Imm); + + // For f64 -0.0, we need to insert a fneg.d idiom. + if (NegZeroF64) + Res = CurDAG->getMachineNode(RISCV::FSGNJN_D, DL, VT, SDValue(Res, 0), + SDValue(Res, 0)); + + ReplaceNode(Node, Res); return; } case ISD::SHL: { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td index cd6ff9e62b5ea..0adb000854248 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -348,11 +348,6 @@ def SplitF64Pseudo let Predicates = [HasStdExtD, IsRV32] in { -/// Float constants -def : Pat<(f64 (fpimm0)), (FCVT_D_W (i32 X0))>; -def : Pat<(f64 (fpimmneg0)), (FSGNJN_D (FCVT_D_W (i32 X0)), - (FCVT_D_W (i32 X0)))>; - // double->[u]int. Round-to-zero must be used. def : Pat<(i32 (any_fp_to_sint FPR64:$rs1)), (FCVT_W_D FPR64:$rs1, 0b001)>; def : Pat<(i32 (any_fp_to_uint FPR64:$rs1)), (FCVT_WU_D FPR64:$rs1, 0b001)>; @@ -374,11 +369,6 @@ def : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_D_WU GPR:$rs1)>; let Predicates = [HasStdExtD, IsRV64] in { -/// Float constants -def : Pat<(f64 (fpimm0)), (FMV_D_X (i64 X0))>; -def : Pat<(f64 (fpimmneg0)), (FSGNJN_D (FMV_D_X (i64 X0)), - (FMV_D_X (i64 X0)))>; - // Moves (no conversion) def : Pat<(bitconvert (i64 GPR:$rs1)), (FMV_D_X GPR:$rs1)>; def : Pat<(i64 (bitconvert FPR64:$rs1)), (FMV_X_D FPR64:$rs1)>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td index 966e4cfaf129b..a771e2950b604 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -436,7 +436,6 @@ def : InstAlias<"fge.s $rd, $rs, $rt", /// Floating point constants def fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>; -def fpimmneg0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(-0.0); }]>; /// Generic pattern classes class PatSetCC @@ -452,9 +451,6 @@ class PatFprFprDynFrm; - /// Float conversion operations // [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td index 28c40a6b31c8b..43e8fa1dfe0e3 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -326,9 +326,6 @@ defm : LdPat; defm : StPat; -/// Floating point constant +0.0 -def : Pat<(f16 (fpimm0)), (FMV_H_X X0)>; - /// Float conversion operations // f32 -> f16, f16 -> f32