mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
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 llvm-svn: 235215
This commit is contained in:
parent
029b9d94fb
commit
f8369b5437
@ -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
|
||||
|
@ -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>. ==>
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
|
@ -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*/,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -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.
|
||||
|
1287
test/CodeGen/ARM/fp16-promote.ll
Normal file
1287
test/CodeGen/ARM/fp16-promote.ll
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user