mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 22:58:50 +00:00
CodeGen: generate single libcall for fptrunc -> f16 operations.
Previously we asserted on this code. Currently compiler-rt doesn't actually implement any of these new libcalls, but external help is pretty much the only viable option for LLVM. I've followed the much more generic "__truncST2" naming, as opposed to the odd name for f32 -> f16 truncation. This can obviously be changed later, or overridden by any targets that need to. llvm-svn: 213252
This commit is contained in:
parent
81da81acc1
commit
21a41cb9a1
@ -210,6 +210,10 @@ namespace RTLIB {
|
||||
FPEXT_F32_F64,
|
||||
FPEXT_F16_F32,
|
||||
FPROUND_F32_F16,
|
||||
FPROUND_F64_F16,
|
||||
FPROUND_F80_F16,
|
||||
FPROUND_F128_F16,
|
||||
FPROUND_PPCF128_F16,
|
||||
FPROUND_F64_F32,
|
||||
FPROUND_F80_F32,
|
||||
FPROUND_F128_F32,
|
||||
|
@ -3529,13 +3529,13 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
|
||||
DAG.getNode(ISD::FP_EXTEND, dl, Node->getValueType(0), Res));
|
||||
break;
|
||||
}
|
||||
case ISD::FP_TO_FP16:
|
||||
// Can't use two-step truncation here because the rounding may be
|
||||
// significant.
|
||||
assert(Node->getOperand(0).getValueType() == MVT::f32 &&
|
||||
"Don't know libcall for FPROUND_F64_F16");
|
||||
Results.push_back(ExpandLibCall(RTLIB::FPROUND_F32_F16, Node, false));
|
||||
case ISD::FP_TO_FP16: {
|
||||
RTLIB::Libcall LC =
|
||||
RTLIB::getFPROUND(Node->getOperand(0).getValueType(), MVT::f16);
|
||||
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unable to expand fp_to_fp16");
|
||||
Results.push_back(ExpandLibCall(LC, Node, false));
|
||||
break;
|
||||
}
|
||||
case ISD::ConstantFP: {
|
||||
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
|
||||
// Check to see if this FP immediate is already legal.
|
||||
|
@ -632,10 +632,10 @@ bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
|
||||
|
||||
case ISD::BITCAST: Res = SoftenFloatOp_BITCAST(N); break;
|
||||
case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break;
|
||||
case ISD::FP_TO_FP16: // Same as FP_ROUND for softening purposes
|
||||
case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break;
|
||||
case ISD::FP_TO_SINT: Res = SoftenFloatOp_FP_TO_SINT(N); break;
|
||||
case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_UINT(N); break;
|
||||
case ISD::FP_TO_FP16: Res = SoftenFloatOp_FP_TO_FP16(N); break;
|
||||
case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
|
||||
case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
|
||||
case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
|
||||
@ -662,10 +662,15 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) {
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
|
||||
// We actually deal with the partially-softened FP_TO_FP16 node too, which
|
||||
// returns an i16 so doesn't meet the constraints necessary for FP_ROUND.
|
||||
assert(N->getOpcode() == ISD::FP_ROUND || N->getOpcode() == ISD::FP_TO_FP16);
|
||||
|
||||
EVT SVT = N->getOperand(0).getValueType();
|
||||
EVT RVT = N->getValueType(0);
|
||||
EVT FloatRVT = N->getOpcode() == ISD::FP_TO_FP16 ? MVT::f16 : RVT;
|
||||
|
||||
RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT);
|
||||
RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, FloatRVT);
|
||||
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
|
||||
|
||||
SDValue Op = GetSoftenedFloat(N->getOperand(0));
|
||||
@ -711,15 +716,6 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_UINT(SDNode *N) {
|
||||
return TLI.makeLibCall(DAG, LC, RVT, &Op, 1, false, SDLoc(N)).first;
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_FP16(SDNode *N) {
|
||||
assert(N->getOperand(0).getValueType() == MVT::f32 &&
|
||||
"Cannot soften in one step");
|
||||
EVT RVT = N->getValueType(0);
|
||||
RTLIB::Libcall LC = RTLIB::FPROUND_F32_F16;
|
||||
SDValue Op = GetSoftenedFloat(N->getOperand(0));
|
||||
return TLI.makeLibCall(DAG, LC, RVT, &Op, 1, false, SDLoc(N)).first;
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
|
||||
SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
|
||||
ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
|
||||
|
@ -428,7 +428,6 @@ private:
|
||||
SDValue SoftenFloatOp_FP_ROUND(SDNode *N);
|
||||
SDValue SoftenFloatOp_FP_TO_SINT(SDNode *N);
|
||||
SDValue SoftenFloatOp_FP_TO_UINT(SDNode *N);
|
||||
SDValue SoftenFloatOp_FP_TO_FP16(SDNode *N);
|
||||
SDValue SoftenFloatOp_SELECT_CC(SDNode *N);
|
||||
SDValue SoftenFloatOp_SETCC(SDNode *N);
|
||||
SDValue SoftenFloatOp_STORE(SDNode *N, unsigned OpNo);
|
||||
|
@ -220,6 +220,10 @@ static void InitLibcallNames(const char **Names, const Triple &TT) {
|
||||
Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2";
|
||||
Names[RTLIB::FPEXT_F16_F32] = "__gnu_h2f_ieee";
|
||||
Names[RTLIB::FPROUND_F32_F16] = "__gnu_f2h_ieee";
|
||||
Names[RTLIB::FPROUND_F64_F16] = "__truncdfhf2";
|
||||
Names[RTLIB::FPROUND_F80_F16] = "__truncxfhf2";
|
||||
Names[RTLIB::FPROUND_F128_F16] = "__trunctfhf2";
|
||||
Names[RTLIB::FPROUND_PPCF128_F16] = "__trunctfhf2";
|
||||
Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2";
|
||||
Names[RTLIB::FPROUND_F80_F32] = "__truncxfsf2";
|
||||
Names[RTLIB::FPROUND_F128_F32] = "__trunctfsf2";
|
||||
@ -434,7 +438,18 @@ RTLIB::Libcall RTLIB::getFPEXT(EVT OpVT, EVT RetVT) {
|
||||
/// getFPROUND - Return the FPROUND_*_* value for the given types, or
|
||||
/// UNKNOWN_LIBCALL if there is none.
|
||||
RTLIB::Libcall RTLIB::getFPROUND(EVT OpVT, EVT RetVT) {
|
||||
if (RetVT == MVT::f32) {
|
||||
if (RetVT == MVT::f16) {
|
||||
if (OpVT == MVT::f32)
|
||||
return FPROUND_F32_F16;
|
||||
if (OpVT == MVT::f64)
|
||||
return FPROUND_F64_F16;
|
||||
if (OpVT == MVT::f80)
|
||||
return FPROUND_F80_F16;
|
||||
if (OpVT == MVT::f128)
|
||||
return FPROUND_F128_F16;
|
||||
if (OpVT == MVT::ppcf128)
|
||||
return FPROUND_PPCF128_F16;
|
||||
} else if (RetVT == MVT::f32) {
|
||||
if (OpVT == MVT::f64)
|
||||
return FPROUND_F64_F32;
|
||||
if (OpVT == MVT::f80)
|
||||
|
@ -523,9 +523,11 @@ void X86TargetLowering::resetOperationActions() {
|
||||
setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
|
||||
}
|
||||
|
||||
// There's never any support for extending beyond MVT::f32.
|
||||
// There's never any support for operations beyond MVT::f32.
|
||||
setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
|
||||
setOperationAction(ISD::FP16_TO_FP, MVT::f80, Expand);
|
||||
setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
|
||||
setOperationAction(ISD::FP_TO_FP16, MVT::f80, Expand);
|
||||
|
||||
if (Subtarget->hasPOPCNT()) {
|
||||
setOperationAction(ISD::CTPOP , MVT::i8 , Promote);
|
||||
|
@ -73,6 +73,17 @@ define double @test4(i16* nocapture %src) {
|
||||
; F16C: vcvtss2sd
|
||||
; F16C: ret
|
||||
|
||||
|
||||
define i16 @test5(double %src) {
|
||||
%val = tail call i16 @llvm.convert.to.fp16.f64(double %src)
|
||||
ret i16 %val
|
||||
}
|
||||
; CHECK-LABEL: test5:
|
||||
; LIBCALL: jmp __truncdfhf2
|
||||
; SOFTFLOAT: callq __truncdfhf2
|
||||
; F16C: jmp __truncdfhf2
|
||||
|
||||
declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone
|
||||
declare i16 @llvm.convert.to.fp16.f32(float) nounwind readnone
|
||||
declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone
|
||||
declare i16 @llvm.convert.to.fp16.f64(double) nounwind readnone
|
||||
|
Loading…
Reference in New Issue
Block a user