Add support to promote f16 to f32

Summary:
This patch adds legalization support to operate on FP16 as a load/store type
and do operations on it as floats.

Tests for ARM are added to test/CodeGen/ARM/fp16-promote.ll

Reviewers: srhines, t.p.northover

Differential Revision: http://reviews.llvm.org/D8755

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235215 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Pirama Arumuga Nainar 2015-04-17 18:36:25 +00:00
parent 5a77e65d39
commit 5c1c08cd1f
8 changed files with 1816 additions and 5 deletions

View File

@ -100,7 +100,8 @@ public:
TypeExpandFloat, // Split this float into two of half the size.
TypeScalarizeVector, // Replace this one-element vector with its element.
TypeSplitVector, // Split this vector into two of half the size.
TypeWidenVector // This vector should be widened into a larger vector.
TypeWidenVector, // This vector should be widened into a larger vector.
TypePromoteFloat // Replace this float with a larger one.
};
/// LegalizeKind holds the legalization kind that needs to happen to EVT

View File

@ -307,6 +307,7 @@ namespace {
SDValue visitINSERT_SUBVECTOR(SDNode *N);
SDValue visitMLOAD(SDNode *N);
SDValue visitMSTORE(SDNode *N);
SDValue visitFP_TO_FP16(SDNode *N);
SDValue XformToShuffleWithZero(SDNode *N);
SDValue ReassociateOps(unsigned Opc, SDLoc DL, SDValue LHS, SDValue RHS);
@ -1380,6 +1381,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::INSERT_SUBVECTOR: return visitINSERT_SUBVECTOR(N);
case ISD::MLOAD: return visitMLOAD(N);
case ISD::MSTORE: return visitMSTORE(N);
case ISD::FP_TO_FP16: return visitFP_TO_FP16(N);
}
return SDValue();
}
@ -8161,6 +8163,11 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) {
if (isConstantFPBuildVectorOrConstantFP(N0))
return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, N0);
// fold (fp_extend (fp16_to_fp op)) -> (fp16_to_fp op)
if (N0.getOpcode() == ISD::FP16_TO_FP &&
TLI.getOperationAction(ISD::FP16_TO_FP, VT) == TargetLowering::Legal)
return DAG.getNode(ISD::FP16_TO_FP, SDLoc(N), VT, N0.getOperand(0));
// Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the
// value of X.
if (N0.getOpcode() == ISD::FP_ROUND
@ -12349,6 +12356,16 @@ SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) {
return SDValue();
}
SDValue DAGCombiner::visitFP_TO_FP16(SDNode *N) {
SDValue N0 = N->getOperand(0);
// fold (fp_to_fp16 (fp16_to_fp op)) -> op
if (N0->getOpcode() == ISD::FP16_TO_FP)
return N0->getOperand(0);
return SDValue();
}
/// Returns a vector_shuffle if it able to transform an AND to a vector_shuffle
/// with the destination vector and a zero vector.
/// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==>

View File

@ -1579,3 +1579,420 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
return DAG.getTruncStore(Chain, SDLoc(N), Hi, Ptr,
ST->getMemoryVT(), ST->getMemOperand());
}
//===----------------------------------------------------------------------===//
// Float Operand Promotion
//===----------------------------------------------------------------------===//
//
static ISD::NodeType GetPromotionOpcode(EVT OpVT, EVT RetVT) {
if (OpVT == MVT::f16) {
return ISD::FP16_TO_FP;
} else if (RetVT == MVT::f16) {
return ISD::FP_TO_FP16;
}
report_fatal_error("Attempt at an invalid promotion-related conversion");
}
bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
SDValue R = SDValue();
// Nodes that use a promotion-requiring floating point operand, but doesn't
// produce a promotion-requiring floating point result, need to be legalized
// to use the promoted float operand. Nodes that produce at least one
// promotion-requiring floating point result have their operands legalized as
// a part of PromoteFloatResult.
switch (N->getOpcode()) {
default:
llvm_unreachable("Do not know how to promote this operator's operand!");
case ISD::BITCAST: R = PromoteFloatOp_BITCAST(N, OpNo); break;
case ISD::FCOPYSIGN: R = PromoteFloatOp_FCOPYSIGN(N, OpNo); break;
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: R = PromoteFloatOp_FP_TO_XINT(N, OpNo); break;
case ISD::FP_EXTEND: R = PromoteFloatOp_FP_EXTEND(N, OpNo); break;
case ISD::SELECT_CC: R = PromoteFloatOp_SELECT_CC(N, OpNo); break;
case ISD::SETCC: R = PromoteFloatOp_SETCC(N, OpNo); break;
case ISD::STORE: R = PromoteFloatOp_STORE(N, OpNo); break;
}
if (R.getNode())
ReplaceValueWith(SDValue(N, 0), R);
return false;
}
SDValue DAGTypeLegalizer::PromoteFloatOp_BITCAST(SDNode *N, unsigned OpNo) {
SDValue Op = N->getOperand(0);
EVT OpVT = Op->getValueType(0);
EVT VT = N->getValueType(0);
EVT IVT = EVT::getIntegerVT(*DAG.getContext(), OpVT.getSizeInBits());
assert (IVT == VT && "Bitcast to type of different size");
SDValue Promoted = GetPromotedFloat(N->getOperand(0));
EVT PromotedVT = Promoted->getValueType(0);
// Convert the promoted float value to the desired IVT.
return DAG.getNode(GetPromotionOpcode(PromotedVT, OpVT), SDLoc(N), IVT,
Promoted);
}
// Promote Operand 1 of FCOPYSIGN. Operand 0 ought to be handled by
// PromoteFloatRes_FCOPYSIGN.
SDValue DAGTypeLegalizer::PromoteFloatOp_FCOPYSIGN(SDNode *N, unsigned OpNo) {
assert (OpNo == 1 && "Only Operand 1 must need promotion here");
SDValue Op1 = GetPromotedFloat(N->getOperand(1));
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
N->getOperand(0), Op1);
}
// Convert the promoted float value to the desired integer type
SDValue DAGTypeLegalizer::PromoteFloatOp_FP_TO_XINT(SDNode *N, unsigned OpNo) {
SDValue Op = GetPromotedFloat(N->getOperand(0));
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op);
}
SDValue DAGTypeLegalizer::PromoteFloatOp_FP_EXTEND(SDNode *N, unsigned OpNo) {
SDValue Op = GetPromotedFloat(N->getOperand(0));
EVT VT = N->getValueType(0);
// Desired VT is same as promoted type. Use promoted float directly.
if (VT == Op->getValueType(0))
return Op;
// Else, extend the promoted float value to the desired VT.
return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Op);
}
// Promote the float operands used for comparison. The true- and false-
// operands have the same type as the result and are promoted, if needed, by
// PromoteFloatRes_SELECT_CC
SDValue DAGTypeLegalizer::PromoteFloatOp_SELECT_CC(SDNode *N, unsigned OpNo) {
SDValue LHS = GetPromotedFloat(N->getOperand(0));
SDValue RHS = GetPromotedFloat(N->getOperand(1));
return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0),
LHS, RHS, N->getOperand(2), N->getOperand(3),
N->getOperand(4));
}
// Construct a SETCC that compares the promoted values and sets the conditional
// code.
SDValue DAGTypeLegalizer::PromoteFloatOp_SETCC(SDNode *N, unsigned OpNo) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op0 = GetPromotedFloat(N->getOperand(0));
SDValue Op1 = GetPromotedFloat(N->getOperand(1));
ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
return DAG.getSetCC(SDLoc(N), NVT, Op0, Op1, CCCode);
}
// Lower the promoted Float down to the integer value of same size and construct
// a STORE of the integer value.
SDValue DAGTypeLegalizer::PromoteFloatOp_STORE(SDNode *N, unsigned OpNo) {
StoreSDNode *ST = cast<StoreSDNode>(N);
SDValue Val = ST->getValue();
SDLoc DL(N);
SDValue Promoted = GetPromotedFloat(Val);
EVT VT = ST->getOperand(1)->getValueType(0);
EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
SDValue NewVal;
NewVal = DAG.getNode(GetPromotionOpcode(Promoted.getValueType(), VT), DL,
IVT, Promoted);
return DAG.getStore(ST->getChain(), DL, NewVal, ST->getBasePtr(),
ST->getMemOperand());
}
//===----------------------------------------------------------------------===//
// Float Result Promotion
//===----------------------------------------------------------------------===//
void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
SDValue R = SDValue();
switch (N->getOpcode()) {
// These opcodes cannot appear if promotion of FP16 is done in the backend
// instead of Clang
case ISD::FP16_TO_FP:
case ISD::FP_TO_FP16:
default:
llvm_unreachable("Do not know how to promote this operator's result!");
case ISD::BITCAST: R = PromoteFloatRes_BITCAST(N); break;
case ISD::ConstantFP: R = PromoteFloatRes_ConstantFP(N); break;
case ISD::EXTRACT_VECTOR_ELT:
R = PromoteFloatRes_EXTRACT_VECTOR_ELT(N); break;
case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break;
// Unary FP Operations
case ISD::FABS:
case ISD::FCEIL:
case ISD::FCOS:
case ISD::FEXP:
case ISD::FEXP2:
case ISD::FFLOOR:
case ISD::FLOG:
case ISD::FLOG2:
case ISD::FLOG10:
case ISD::FNEARBYINT:
case ISD::FNEG:
case ISD::FRINT:
case ISD::FROUND:
case ISD::FSIN:
case ISD::FSQRT:
case ISD::FTRUNC: R = PromoteFloatRes_UnaryOp(N); break;
// Binary FP Operations
case ISD::FADD:
case ISD::FDIV:
case ISD::FMAXNUM:
case ISD::FMINNUM:
case ISD::FMUL:
case ISD::FPOW:
case ISD::FREM:
case ISD::FSUB: R = PromoteFloatRes_BinOp(N); break;
case ISD::FMA: // FMA is same as FMAD
case ISD::FMAD: R = PromoteFloatRes_FMAD(N); break;
case ISD::FPOWI: R = PromoteFloatRes_FPOWI(N); break;
case ISD::FP_ROUND: R = PromoteFloatRes_FP_ROUND(N); break;
case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break;
case ISD::SELECT: R = PromoteFloatRes_SELECT(N); break;
case ISD::SELECT_CC: R = PromoteFloatRes_SELECT_CC(N); break;
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break;
case ISD::UNDEF: R = PromoteFloatRes_UNDEF(N); break;
}
if (R.getNode())
SetPromotedFloat(SDValue(N, ResNo), R);
}
// Bitcast from i16 to f16: convert the i16 to a f32 value instead.
// At this point, it is not possible to determine if the bitcast value is
// eventually stored to memory or promoted to f32 or promoted to a floating
// point at a higher precision. Some of these cases are handled by FP_EXTEND,
// STORE promotion handlers.
SDValue DAGTypeLegalizer::PromoteFloatRes_BITCAST(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT,
N->getOperand(0));
}
SDValue DAGTypeLegalizer::PromoteFloatRes_ConstantFP(SDNode *N) {
ConstantFPSDNode *CFPNode = cast<ConstantFPSDNode>(N);
EVT VT = N->getValueType(0);
// Get the (bit-cast) APInt of the APFloat and build an integer constant
EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
SDValue C = DAG.getConstant(CFPNode->getValueAPF().bitcastToAPInt(),
IVT);
// Convert the Constant to the desired FP type
// FIXME We might be able to do the conversion during compilation and get rid
// of it from the object code
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, C);
}
// If the Index operand is a constant, try to redirect the extract operation to
// the correct legalized vector. If not, bit-convert the input vector to
// equivalent integer vector. Extract the element as an (bit-cast) integer
// value and convert it to the promoted type.
SDValue DAGTypeLegalizer::PromoteFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) {
SDLoc DL(N);
// If the index is constant, try to extract the value from the legalized
// vector type.
if (isa<ConstantSDNode>(N->getOperand(1))) {
SDValue Vec = N->getOperand(0);
SDValue Idx = N->getOperand(1);
EVT VecVT = Vec->getValueType(0);
EVT EltVT = VecVT.getVectorElementType();
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
switch (getTypeAction(VecVT)) {
default: break;
case TargetLowering::TypeScalarizeVector: {
SDValue Res = GetScalarizedVector(N->getOperand(0));
ReplaceValueWith(SDValue(N, 0), Res);
return SDValue();
}
case TargetLowering::TypeWidenVector: {
Vec = GetWidenedVector(Vec);
SDValue Res = DAG.getNode(N->getOpcode(), DL, EltVT, Vec, Idx);
ReplaceValueWith(SDValue(N, 0), Res);
return SDValue();
}
case TargetLowering::TypeSplitVector: {
SDValue Lo, Hi;
GetSplitVector(Vec, Lo, Hi);
uint64_t LoElts = Lo.getValueType().getVectorNumElements();
SDValue Res;
if (IdxVal < LoElts)
Res = DAG.getNode(N->getOpcode(), DL, EltVT, Lo, Idx);
else
Res = DAG.getNode(N->getOpcode(), DL, EltVT, Hi,
DAG.getConstant(IdxVal - LoElts,
Idx.getValueType()));
ReplaceValueWith(SDValue(N, 0), Res);
return SDValue();
}
}
}
// Bit-convert the input vector to the equivalent integer vector
SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
EVT IVT = NewOp.getValueType().getVectorElementType();
// Extract the element as an (bit-cast) integer value
SDValue NewVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, IVT,
NewOp, N->getOperand(1));
// Convert the element to the desired FP type
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, NewVal);
}
// FCOPYSIGN(X, Y) returns the value of X with the sign of Y. If the result
// needs promotion, so does the argument X. Note that Y, if needed, will be
// handled during operand promotion.
SDValue DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op0 = GetPromotedFloat(N->getOperand(0));
SDValue Op1 = N->getOperand(1);
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
}
// Unary operation where the result and the operand have PromoteFloat type
// action. Construct a new SDNode with the promoted float value of the old
// operand.
SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryOp(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op = GetPromotedFloat(N->getOperand(0));
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op);
}
// Binary operations where the result and both operands have PromoteFloat type
// action. Construct a new SDNode with the promoted float values of the old
// operands.
SDValue DAGTypeLegalizer::PromoteFloatRes_BinOp(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op0 = GetPromotedFloat(N->getOperand(0));
SDValue Op1 = GetPromotedFloat(N->getOperand(1));
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
}
SDValue DAGTypeLegalizer::PromoteFloatRes_FMAD(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op0 = GetPromotedFloat(N->getOperand(0));
SDValue Op1 = GetPromotedFloat(N->getOperand(1));
SDValue Op2 = GetPromotedFloat(N->getOperand(2));
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1, Op2);
}
// Promote the Float (first) operand and retain the Integer (second) operand
SDValue DAGTypeLegalizer::PromoteFloatRes_FPOWI(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDValue Op0 = GetPromotedFloat(N->getOperand(0));
SDValue Op1 = N->getOperand(1);
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
}
// Explicit operation to reduce precision. Reduce the value to half precision
// and promote it back to the legal type.
SDValue DAGTypeLegalizer::PromoteFloatRes_FP_ROUND(SDNode *N) {
SDLoc DL(N);
SDValue Op = N->getOperand(0);
EVT VT = N->getValueType(0);
EVT OpVT = Op->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
// Round promoted float to desired precision
SDValue Round = DAG.getNode(GetPromotionOpcode(OpVT, VT), DL, IVT, Op);
// Promote it back to the legal output type
return DAG.getNode(GetPromotionOpcode(VT, NVT), DL, NVT, Round);
}
SDValue DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) {
LoadSDNode *L = cast<LoadSDNode>(N);
EVT VT = N->getValueType(0);
// Load the value as an integer value with the same number of bits
EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
SDValue newL = DAG.getLoad(L->getAddressingMode(), L->getExtensionType(),
IVT, SDLoc(N), L->getChain(), L->getBasePtr(),
L->getOffset(), L->getPointerInfo(), IVT, L->isVolatile(),
L->isNonTemporal(), false, L->getAlignment(),
L->getAAInfo());
// Legalize the chain result by replacing uses of the old value chain with the
// new one
ReplaceValueWith(SDValue(N, 1), newL.getValue(1));
// Convert the integer value to the desired FP type
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, newL);
}
// Construct a new SELECT node with the promoted true- and false- values.
SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT(SDNode *N) {
SDValue TrueVal = GetPromotedFloat(N->getOperand(1));
SDValue FalseVal = GetPromotedFloat(N->getOperand(2));
return DAG.getNode(ISD::SELECT, SDLoc(N), TrueVal->getValueType(0),
N->getOperand(0), TrueVal, FalseVal);
}
// Construct a new SELECT_CC node with the promoted true- and false- values.
// The operands used for comparison are promoted by PromoteFloatOp_SELECT_CC.
SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT_CC(SDNode *N) {
SDValue TrueVal = GetPromotedFloat(N->getOperand(2));
SDValue FalseVal = GetPromotedFloat(N->getOperand(3));
return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0),
N->getOperand(0), N->getOperand(1), TrueVal, FalseVal,
N->getOperand(4));
}
// Construct a SDNode that transforms the SINT or UINT operand to the promoted
// float type.
SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
EVT VT = N->getValueType(0);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, N->getOperand(0));
}
SDValue DAGTypeLegalizer::PromoteFloatRes_UNDEF(SDNode *N) {
return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
N->getValueType(0)));
}

View File

@ -251,6 +251,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_BITCAST(SDNode *N) {
case TargetLowering::TypeSoftenFloat:
// Promote the integer operand by hand.
return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, GetSoftenedFloat(InOp));
case TargetLowering::TypePromoteFloat: {
// Convert the promoted float by hand.
if (NOutVT.bitsEq(NInVT)) {
SDValue PromotedOp = GetPromotedFloat(InOp);
SDValue Trunc = DAG.getNode(ISD::FP_TO_FP16, dl, NOutVT, PromotedOp);
return DAG.getNode(ISD::AssertZext, dl, NOutVT, Trunc,
DAG.getValueType(OutVT));
}
break;
}
case TargetLowering::TypeExpandInteger:
case TargetLowering::TypeExpandFloat:
break;
@ -1845,7 +1855,11 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDLoc dl(N);
EVT VT = N->getValueType(0);
SDValue Op = N->getOperand(0);
if (getTypeAction(Op.getValueType()) == TargetLowering::TypePromoteFloat)
Op = GetPromotedFloat(Op);
RTLIB::Libcall LC = RTLIB::getFPTOSINT(Op.getValueType(), VT);
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!");
SplitInteger(TLI.makeLibCall(DAG, LC, VT, &Op, 1, true/*irrelevant*/,
@ -1857,7 +1871,11 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDLoc dl(N);
EVT VT = N->getValueType(0);
SDValue Op = N->getOperand(0);
if (getTypeAction(Op.getValueType()) == TargetLowering::TypePromoteFloat)
Op = GetPromotedFloat(Op);
RTLIB::Libcall LC = RTLIB::getFPTOUINT(Op.getValueType(), VT);
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!");
SplitInteger(TLI.makeLibCall(DAG, LC, VT, &Op, 1, false/*irrelevant*/,

View File

@ -259,6 +259,10 @@ bool DAGTypeLegalizer::run() {
WidenVectorResult(N, i);
Changed = true;
goto NodeDone;
case TargetLowering::TypePromoteFloat:
PromoteFloatResult(N, i);
Changed = true;
goto NodeDone;
}
}
@ -308,6 +312,10 @@ ScanOperands:
NeedsReanalyzing = WidenVectorOperand(N, i);
Changed = true;
break;
case TargetLowering::TypePromoteFloat:
NeedsReanalyzing = PromoteFloatOperand(N, i);
Changed = true;
break;
}
break;
}
@ -753,6 +761,17 @@ void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) {
OpEntry = Result;
}
void DAGTypeLegalizer::SetPromotedFloat(SDValue Op, SDValue Result) {
assert(Result.getValueType() ==
TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) &&
"Invalid type for promoted float");
AnalyzeNewValue(Result);
SDValue &OpEntry = PromotedFloats[Op];
assert(!OpEntry.getNode() && "Node is already promoted!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetScalarizedVector(SDValue Op, SDValue Result) {
// Note that in some cases vector operation operands may be greater than
// the vector element type. For example BUILD_VECTOR of type <1 x i1> with

View File

@ -93,6 +93,11 @@ private:
/// the same size, this map indicates the converted value to use.
SmallDenseMap<SDValue, SDValue, 8> SoftenedFloats;
/// PromotedFloats - For floating point nodes that have a smaller precision
/// than the smallest supported precision, this map indicates what promoted
/// value to use.
SmallDenseMap<SDValue, SDValue, 8> PromotedFloats;
/// ExpandedFloats - For float nodes that need to be expanded this map
/// indicates which operands are the expanded version of the input.
SmallDenseMap<SDValue, std::pair<SDValue, SDValue>, 8> ExpandedFloats;
@ -499,6 +504,44 @@ private:
void FloatExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS,
ISD::CondCode &CCCode, SDLoc dl);
//===--------------------------------------------------------------------===//
// Float promotion support: LegalizeFloatTypes.cpp
//===--------------------------------------------------------------------===//
SDValue GetPromotedFloat(SDValue Op) {
SDValue &PromotedOp = PromotedFloats[Op];
RemapValue(PromotedOp);
assert(PromotedOp.getNode() && "Operand wasn't promoted?");
return PromotedOp;
}
void SetPromotedFloat(SDValue Op, SDValue Result);
void PromoteFloatResult(SDNode *N, unsigned ResNo);
SDValue PromoteFloatRes_BITCAST(SDNode *N);
SDValue PromoteFloatRes_BinOp(SDNode *N);
SDValue PromoteFloatRes_ConstantFP(SDNode *N);
SDValue PromoteFloatRes_EXTRACT_VECTOR_ELT(SDNode *N);
SDValue PromoteFloatRes_FCOPYSIGN(SDNode *N);
SDValue PromoteFloatRes_FMAD(SDNode *N);
SDValue PromoteFloatRes_FPOWI(SDNode *N);
SDValue PromoteFloatRes_FP_ROUND(SDNode *N);
SDValue PromoteFloatRes_LOAD(SDNode *N);
SDValue PromoteFloatRes_SELECT(SDNode *N);
SDValue PromoteFloatRes_SELECT_CC(SDNode *N);
SDValue PromoteFloatRes_UnaryOp(SDNode *N);
SDValue PromoteFloatRes_UNDEF(SDNode *N);
SDValue PromoteFloatRes_XINT_TO_FP(SDNode *N);
bool PromoteFloatOperand(SDNode *N, unsigned ResNo);
SDValue PromoteFloatOp_BITCAST(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_FCOPYSIGN(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_FP_EXTEND(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_FP_TO_XINT(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_STORE(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_SELECT_CC(SDNode *N, unsigned OpNo);
SDValue PromoteFloatOp_SETCC(SDNode *N, unsigned OpNo);
//===--------------------------------------------------------------------===//
// Scalarization Support: LegalizeVectorTypes.cpp
//===--------------------------------------------------------------------===//

View File

@ -1256,10 +1256,19 @@ void TargetLoweringBase::computeRegisterProperties(
}
if (!isTypeLegal(MVT::f16)) {
NumRegistersForVT[MVT::f16] = NumRegistersForVT[MVT::i16];
RegisterTypeForVT[MVT::f16] = RegisterTypeForVT[MVT::i16];
TransformToType[MVT::f16] = MVT::i16;
ValueTypeActions.setTypeAction(MVT::f16, TypeSoftenFloat);
// If the target has native f32 support, promote f16 operations to f32. If
// f32 is not supported, generate soft float library calls.
if (isTypeLegal(MVT::f32)) {
NumRegistersForVT[MVT::f16] = NumRegistersForVT[MVT::f32];
RegisterTypeForVT[MVT::f16] = RegisterTypeForVT[MVT::f32];
TransformToType[MVT::f16] = MVT::f32;
ValueTypeActions.setTypeAction(MVT::f16, TypePromoteFloat);
} else {
NumRegistersForVT[MVT::f16] = NumRegistersForVT[MVT::i16];
RegisterTypeForVT[MVT::f16] = RegisterTypeForVT[MVT::i16];
TransformToType[MVT::f16] = MVT::i16;
ValueTypeActions.setTypeAction(MVT::f16, TypeSoftenFloat);
}
}
// Loop over all of the vector value types to see which need transformations.

File diff suppressed because it is too large Load Diff