}
case ISD::ConstantFP: {
const APFloat &APF = cast<ConstantFPSDNode>(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:
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: {
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)>;
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)>;
/// 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<RegisterClass Ty, SDPatternOperator OpNode, CondCode Cond, RVInst Inst>
let Predicates = [HasStdExtF] in {
-/// Float constants
-def : Pat<(f32 (fpimm0)), (FMV_W_X X0)>;
-
/// Float conversion operations
// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so