mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-17 00:27:31 +00:00
Implement a correct ui64->f32 conversion. The old
one was subject to double rounding in extreme cases. llvm-svn: 103744
This commit is contained in:
parent
5e115a09ec
commit
9f19b6a761
@ -2026,6 +2026,7 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
||||
return Result;
|
||||
}
|
||||
assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
|
||||
// Code below here assumes !isSigned without checking again.
|
||||
|
||||
// Implementation of unsigned i64 to f64 following the algorithm in
|
||||
// __floatundidf in compiler_rt. This implementation has the advantage
|
||||
@ -2051,6 +2052,41 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
||||
return DAG.getNode(ISD::FADD, dl, MVT::f64, LoFlt, HiSub);
|
||||
}
|
||||
|
||||
// Implementation of unsigned i64 to f32. This implementation has the
|
||||
// advantage of performing rounding correctly.
|
||||
// TODO: Generalize this for use with other types.
|
||||
if (Op0.getValueType() == MVT::i64 && DestVT == MVT::f32) {
|
||||
EVT SHVT = TLI.getShiftAmountTy();
|
||||
|
||||
SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0,
|
||||
DAG.getConstant(UINT64_C(0xfffffffffffff800), MVT::i64));
|
||||
SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i64, And,
|
||||
DAG.getConstant(UINT64_C(0x800), MVT::i64));
|
||||
SDValue And2 = DAG.getNode(ISD::AND, dl, MVT::i64, Op0,
|
||||
DAG.getConstant(UINT64_C(0x7ff), MVT::i64));
|
||||
SDValue Ne = DAG.getSetCC(dl, TLI.getSetCCResultType(MVT::i64),
|
||||
And2, DAG.getConstant(UINT64_C(0), MVT::i64), ISD::SETNE);
|
||||
SDValue Sel = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ne, Or, Op0);
|
||||
SDValue Ge = DAG.getSetCC(dl, TLI.getSetCCResultType(MVT::i64),
|
||||
Op0, DAG.getConstant(UINT64_C(0x0020000000000000), MVT::i64),
|
||||
ISD::SETUGE);
|
||||
SDValue Sel2 = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ge, Sel, Op0);
|
||||
|
||||
SDValue Sh = DAG.getNode(ISD::SRL, dl, MVT::i64, Sel2,
|
||||
DAG.getConstant(32, SHVT));
|
||||
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Sh);
|
||||
SDValue Fcvt = DAG.getNode(ISD::UINT_TO_FP, dl, MVT::f64, Trunc);
|
||||
SDValue TwoP32 =
|
||||
DAG.getConstantFP(BitsToDouble(UINT64_C(0x41f0000000000000)), MVT::f64);
|
||||
SDValue Fmul = DAG.getNode(ISD::FMUL, dl, MVT::f64, TwoP32, Fcvt);
|
||||
SDValue Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Sel2);
|
||||
SDValue Fcvt2 = DAG.getNode(ISD::UINT_TO_FP, dl, MVT::f64, Lo);
|
||||
SDValue Fadd = DAG.getNode(ISD::FADD, dl, MVT::f64, Fmul, Fcvt2);
|
||||
return DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Fadd,
|
||||
DAG.getIntPtrConstant(0));
|
||||
|
||||
}
|
||||
|
||||
SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0);
|
||||
|
||||
SDValue SignSet = DAG.getSetCC(dl, TLI.getSetCCResultType(Op0.getValueType()),
|
||||
|
Loading…
Reference in New Issue
Block a user