Expand Up
@@ -147,9 +147,9 @@ class SelectionDAGLegalize {
SDValue ExpandConstantFP (ConstantFPSDNode *CFP, bool UseCP);
std::pair<SDValue, SDValue> ExpandAtomic (SDNode *Node);
void ExpandNode (SDNode *Node);
// if ExpandNode returns false, LegalizeOp falls back to ConvertNodeToLibcall
bool ExpandNode (SDNode *Node);
void ConvertNodeToLibcall (SDNode *Node);
void PromoteNode (SDNode *Node);
public:
Expand Down
Expand Up
@@ -1390,7 +1390,11 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
}
// FALL THROUGH
case TargetLowering::Expand:
ExpandNode (Node);
if (ExpandNode (Node))
return ;
// FALL THROUGH
case TargetLowering::LibCall:
ConvertNodeToLibcall (Node);
return ;
case TargetLowering::Promote:
PromoteNode (Node);
Expand Down
Expand Up
@@ -2842,16 +2846,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
}
}
std::pair <SDValue, SDValue> SelectionDAGLegalize::ExpandAtomic (SDNode *Node) {
unsigned Opc = Node->getOpcode ();
MVT VT = cast<AtomicSDNode>(Node)->getMemoryVT ().getSimpleVT ();
RTLIB::Libcall LC = RTLIB::getATOMIC (Opc, VT);
assert (LC != RTLIB::UNKNOWN_LIBCALL && " Unexpected atomic op or value type!" );
return ExpandChainLibCall (LC, Node, false );
}
void SelectionDAGLegalize::ExpandNode (SDNode *Node) {
bool SelectionDAGLegalize::ExpandNode (SDNode *Node) {
SmallVector<SDValue, 8 > Results;
SDLoc dl (Node);
SDValue Tmp1, Tmp2, Tmp3, Tmp4;
Expand Down
Expand Up
@@ -2898,24 +2893,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back (DAG.getConstant (0 , dl, MVT::i32));
Results.push_back (Node->getOperand (0 ));
break ;
case ISD::ATOMIC_FENCE: {
// If the target didn't lower this, lower it to '__sync_synchronize()' call
// FIXME: handle "fence singlethread" more efficiently.
TargetLowering::ArgListTy Args;
TargetLowering::CallLoweringInfo CLI (DAG);
CLI.setDebugLoc (dl)
.setChain (Node->getOperand (0 ))
.setCallee (CallingConv::C, Type::getVoidTy (*DAG.getContext ()),
DAG.getExternalSymbol (" __sync_synchronize" ,
TLI.getPointerTy (DAG.getDataLayout ())),
std::move (Args), 0 );
std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo (CLI);
Results.push_back (CallResult.second );
break ;
}
case ISD::ATOMIC_LOAD: {
// There is no libcall for atomic load; fake it with ATOMIC_CMP_SWAP.
SDValue Zero = DAG.getConstant (0 , dl, Node->getValueType (0 ));
Expand Down
Expand Up
@@ -2943,26 +2920,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back (Swap.getValue (1 ));
break ;
}
// By default, atomic intrinsics are marked Legal and lowered. Targets
// which don't support them directly, however, may want libcalls, in which
// case they mark them Expand, and we get here.
case ISD::ATOMIC_SWAP:
case ISD::ATOMIC_LOAD_ADD:
case ISD::ATOMIC_LOAD_SUB:
case ISD::ATOMIC_LOAD_AND:
case ISD::ATOMIC_LOAD_OR:
case ISD::ATOMIC_LOAD_XOR:
case ISD::ATOMIC_LOAD_NAND:
case ISD::ATOMIC_LOAD_MIN:
case ISD::ATOMIC_LOAD_MAX:
case ISD::ATOMIC_LOAD_UMIN:
case ISD::ATOMIC_LOAD_UMAX:
case ISD::ATOMIC_CMP_SWAP: {
std::pair<SDValue, SDValue> Tmp = ExpandAtomic (Node);
Results.push_back (Tmp.first );
Results.push_back (Tmp.second );
break ;
}
case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: {
// Expanding an ATOMIC_CMP_SWAP_WITH_SUCCESS produces an ATOMIC_CMP_SWAP and
// splits out the success value as a comparison. Expanding the resulting
Expand Down
Expand Up
@@ -3001,21 +2958,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
}
break ;
}
case ISD::TRAP: {
// If this operation is not supported, lower it to 'abort()' call
TargetLowering::ArgListTy Args;
TargetLowering::CallLoweringInfo CLI (DAG);
CLI.setDebugLoc (dl)
.setChain (Node->getOperand (0 ))
.setCallee (CallingConv::C, Type::getVoidTy (*DAG.getContext ()),
DAG.getExternalSymbol (" abort" ,
TLI.getPointerTy (DAG.getDataLayout ())),
std::move (Args), 0 );
std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo (CLI);
Results.push_back (CallResult.second );
break ;
}
case ISD::FP_ROUND:
case ISD::BITCAST:
Tmp1 = EmitStackConvert (Node->getOperand (0 ), Node->getValueType (0 ),
Expand Down
Expand Up
@@ -3286,163 +3228,37 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
break ;
}
case ISD::FMINNUM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMIN_F32, RTLIB::FMIN_F64,
RTLIB::FMIN_F80, RTLIB::FMIN_F128,
RTLIB::FMIN_PPCF128));
break ;
case ISD::FMAXNUM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMAX_F32, RTLIB::FMAX_F64,
RTLIB::FMAX_F80, RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128));
break ;
case ISD::FSQRT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
RTLIB::SQRT_F80, RTLIB::SQRT_F128,
RTLIB::SQRT_PPCF128));
break ;
case ISD::FSIN:
case ISD::FCOS: {
EVT VT = Node->getValueType (0 );
bool isSIN = Node->getOpcode () == ISD::FSIN;
// Turn fsin / fcos into ISD::FSINCOS node if there are a pair of fsin /
// fcos which share the same operand and both are used.
if ((TLI.isOperationLegalOrCustom (ISD::FSINCOS, VT) ||
canCombineSinCosLibcall (Node, TLI, TM))
&& useSinCos (Node)) {
SDVTList VTs = DAG.getVTList (VT, VT);
Tmp1 = DAG.getNode (ISD::FSINCOS, dl, VTs, Node->getOperand (0 ));
if (!isSIN )
if (Node-> getOpcode () == ISD::FCOS )
Tmp1 = Tmp1.getValue (1 );
Results.push_back (Tmp1);
} else if (isSIN) {
Results.push_back (ExpandFPLibCall (Node, RTLIB::SIN_F32, RTLIB::SIN_F64,
RTLIB::SIN_F80, RTLIB::SIN_F128,
RTLIB::SIN_PPCF128));
} else {
Results.push_back (ExpandFPLibCall (Node, RTLIB::COS_F32, RTLIB::COS_F64,
RTLIB::COS_F80, RTLIB::COS_F128,
RTLIB::COS_PPCF128));
}
break ;
}
case ISD::FSINCOS:
// Expand into sincos libcall.
ExpandSinCosLibCall (Node, Results);
break ;
case ISD::FLOG:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
RTLIB::LOG_F80, RTLIB::LOG_F128,
RTLIB::LOG_PPCF128));
break ;
case ISD::FLOG2:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
RTLIB::LOG2_F80, RTLIB::LOG2_F128,
RTLIB::LOG2_PPCF128));
break ;
case ISD::FLOG10:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
RTLIB::LOG10_F80, RTLIB::LOG10_F128,
RTLIB::LOG10_PPCF128));
break ;
case ISD::FEXP:
Results.push_back (ExpandFPLibCall (Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
RTLIB::EXP_F80, RTLIB::EXP_F128,
RTLIB::EXP_PPCF128));
break ;
case ISD::FEXP2:
Results.push_back (ExpandFPLibCall (Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
RTLIB::EXP2_F80, RTLIB::EXP2_F128,
RTLIB::EXP2_PPCF128));
break ;
case ISD::FTRUNC:
Results.push_back (ExpandFPLibCall (Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
RTLIB::TRUNC_F80, RTLIB::TRUNC_F128,
RTLIB::TRUNC_PPCF128));
break ;
case ISD::FFLOOR:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64,
RTLIB::FLOOR_F80, RTLIB::FLOOR_F128,
RTLIB::FLOOR_PPCF128));
break ;
case ISD::FCEIL:
Results.push_back (ExpandFPLibCall (Node, RTLIB::CEIL_F32, RTLIB::CEIL_F64,
RTLIB::CEIL_F80, RTLIB::CEIL_F128,
RTLIB::CEIL_PPCF128));
break ;
case ISD::FRINT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::RINT_F32, RTLIB::RINT_F64,
RTLIB::RINT_F80, RTLIB::RINT_F128,
RTLIB::RINT_PPCF128));
break ;
case ISD::FNEARBYINT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::NEARBYINT_F32,
RTLIB::NEARBYINT_F64,
RTLIB::NEARBYINT_F80,
RTLIB::NEARBYINT_F128,
RTLIB::NEARBYINT_PPCF128));
break ;
case ISD::FROUND:
Results.push_back (ExpandFPLibCall (Node, RTLIB::ROUND_F32,
RTLIB::ROUND_F64,
RTLIB::ROUND_F80,
RTLIB::ROUND_F128,
RTLIB::ROUND_PPCF128));
break ;
case ISD::FPOWI:
Results.push_back (ExpandFPLibCall (Node, RTLIB::POWI_F32, RTLIB::POWI_F64,
RTLIB::POWI_F80, RTLIB::POWI_F128,
RTLIB::POWI_PPCF128));
break ;
case ISD::FPOW:
Results.push_back (ExpandFPLibCall (Node, RTLIB::POW_F32, RTLIB::POW_F64,
RTLIB::POW_F80, RTLIB::POW_F128,
RTLIB::POW_PPCF128));
break ;
case ISD::FDIV:
Results.push_back (ExpandFPLibCall (Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
RTLIB::DIV_F80, RTLIB::DIV_F128,
RTLIB::DIV_PPCF128));
break ;
case ISD::FREM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::REM_F32, RTLIB::REM_F64,
RTLIB::REM_F80, RTLIB::REM_F128,
RTLIB::REM_PPCF128));
break ;
case ISD::FMA:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMA_F32, RTLIB::FMA_F64,
RTLIB::FMA_F80, RTLIB::FMA_F128,
RTLIB::FMA_PPCF128));
break ;
case ISD::FMAD:
llvm_unreachable (" Illegal fmad should never be formed" );
case ISD::FADD:
Results.push_back (ExpandFPLibCall (Node, RTLIB::ADD_F32, RTLIB::ADD_F64,
RTLIB::ADD_F80, RTLIB::ADD_F128,
RTLIB::ADD_PPCF128));
break ;
case ISD::FMUL:
Results.push_back (ExpandFPLibCall (Node, RTLIB::MUL_F32, RTLIB::MUL_F64,
RTLIB::MUL_F80, RTLIB::MUL_F128,
RTLIB::MUL_PPCF128));
break ;
case ISD::FP16_TO_FP: {
if (Node->getValueType (0 ) == MVT::f32) {
Results.push_back (ExpandLibCall (RTLIB::FPEXT_F16_F32, Node, false ));
break ;
case ISD::FP16_TO_FP:
if (Node->getValueType (0 ) != MVT::f32) {
// We can extend to types bigger than f32 in two steps without changing
// the result. Since "f16 -> f32" is much more commonly available, give
// CodeGen the option of emitting that before resorting to a libcall.
SDValue Res =
DAG.getNode (ISD::FP16_TO_FP, dl, MVT::f32, Node->getOperand (0 ));
Results.push_back (
DAG.getNode (ISD::FP_EXTEND, dl, Node->getValueType (0 ), Res));
}
// We can extend to types bigger than f32 in two steps without changing the
// result. Since "f16 -> f32" is much more commonly available, give CodeGen
// the option of emitting that before resorting to a libcall.
SDValue Res =
DAG.getNode (ISD::FP16_TO_FP, dl, MVT::f32, Node->getOperand (0 ));
Results.push_back (
DAG.getNode (ISD::FP_EXTEND, dl, Node->getValueType (0 ), Res));
break ;
}
case ISD::FP_TO_FP16: {
case ISD::FP_TO_FP16:
if (!TLI.useSoftFloat () && TM.Options .UnsafeFPMath ) {
SDValue Op = Node->getOperand (0 );
MVT SVT = Op.getSimpleValueType ();
Expand All
@@ -3454,16 +3270,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
DAG.getIntPtrConstant (0 , dl));
Results.push_back (
DAG.getNode (ISD::FP_TO_FP16, dl, MVT::i16, FloatVal));
break ;
}
}
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.
Expand All
@@ -3480,10 +3289,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Tmp1 = DAG.getNode (ISD::FNEG, dl, VT, Node->getOperand (1 ));
Tmp1 = DAG.getNode (ISD::FADD, dl, VT, Node->getOperand (0 ), Tmp1, Flags);
Results.push_back (Tmp1);
} else {
Results.push_back (ExpandFPLibCall (Node, RTLIB::SUB_F32, RTLIB::SUB_F64,
RTLIB::SUB_F80, RTLIB::SUB_F128,
RTLIB::SUB_PPCF128));
}
break ;
}
Expand All
@@ -3510,44 +3315,27 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
if (TLI.isOperationLegalOrCustom (DivRemOpc, VT)) {
SDVTList VTs = DAG.getVTList (VT, VT);
Tmp1 = DAG.getNode (DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue (1 );
Results.push_back (Tmp1);
} else if (TLI.isOperationLegalOrCustom (DivOpc, VT)) {
// X % Y -> X-X/Y*Y
Tmp1 = DAG.getNode (DivOpc, dl, VT, Tmp2, Tmp3);
Tmp1 = DAG.getNode (ISD::MUL, dl, VT, Tmp1, Tmp3);
Tmp1 = DAG.getNode (ISD::SUB, dl, VT, Tmp2, Tmp1);
} else if (isSigned)
Tmp1 = ExpandIntLibCall (Node, true ,
RTLIB::SREM_I8,
RTLIB::SREM_I16, RTLIB::SREM_I32,
RTLIB::SREM_I64, RTLIB::SREM_I128);
else
Tmp1 = ExpandIntLibCall (Node, false ,
RTLIB::UREM_I8,
RTLIB::UREM_I16, RTLIB::UREM_I32,
RTLIB::UREM_I64, RTLIB::UREM_I128);
Results.push_back (Tmp1);
Results.push_back (Tmp1);
}
break ;
}
case ISD::UDIV:
case ISD::SDIV: {
bool isSigned = Node->getOpcode () == ISD::SDIV;
unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
EVT VT = Node->getValueType (0 );
SDVTList VTs = DAG. getVTList (VT , VT);
if (TLI. isOperationLegalOrCustom (DivRemOpc , VT))
if (TLI. isOperationLegalOrCustom (DivRemOpc , VT)) {
SDVTList VTs = DAG. getVTList (VT , VT);
Tmp1 = DAG.getNode (DivRemOpc, dl, VTs, Node->getOperand (0 ),
Node->getOperand (1 ));
else if (isSigned)
Tmp1 = ExpandIntLibCall (Node, true ,
RTLIB::SDIV_I8,
RTLIB::SDIV_I16, RTLIB::SDIV_I32,
RTLIB::SDIV_I64, RTLIB::SDIV_I128);
else
Tmp1 = ExpandIntLibCall (Node, false ,
RTLIB::UDIV_I8,
RTLIB::UDIV_I16, RTLIB::UDIV_I32,
RTLIB::UDIV_I64, RTLIB::UDIV_I128);
Results.push_back (Tmp1);
Results.push_back (Tmp1);
}
break ;
}
case ISD::MULHU:
Expand All
@@ -3563,11 +3351,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back (Tmp1.getValue (1 ));
break ;
}
case ISD::SDIVREM:
case ISD::UDIVREM:
// Expand into divrem libcall
ExpandDivRemLibCall (Node, Results);
break ;
case ISD::MUL: {
EVT VT = Node->getValueType (0 );
SDVTList VTs = DAG.getVTList (VT, VT);
Expand Down
Expand Up
@@ -3610,14 +3393,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
TLI.getShiftAmountTy (HalfType, DAG.getDataLayout ()));
Hi = DAG.getNode (ISD::SHL, dl, VT, Hi, Shift);
Results.push_back (DAG.getNode (ISD::OR, dl, VT, Lo, Hi));
break ;
}
Tmp1 = ExpandIntLibCall (Node, false ,
RTLIB::MUL_I8,
RTLIB::MUL_I16, RTLIB::MUL_I32,
RTLIB::MUL_I64, RTLIB::MUL_I128);
Results.push_back (Tmp1);
break ;
}
case ISD::SADDO:
Expand Down
Expand Up
@@ -4029,6 +3805,254 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
break ;
}
// Replace the original node with the legalized result.
if (Results.empty ())
return false ;
ReplaceNode (Node, Results.data ());
return true ;
}
void SelectionDAGLegalize::ConvertNodeToLibcall (SDNode *Node) {
SmallVector<SDValue, 8 > Results;
SDLoc dl (Node);
SDValue Tmp1, Tmp2, Tmp3, Tmp4;
unsigned Opc = Node->getOpcode ();
switch (Opc) {
case ISD::ATOMIC_FENCE: {
// If the target didn't lower this, lower it to '__sync_synchronize()' call
// FIXME: handle "fence singlethread" more efficiently.
TargetLowering::ArgListTy Args;
TargetLowering::CallLoweringInfo CLI (DAG);
CLI.setDebugLoc (dl)
.setChain (Node->getOperand (0 ))
.setCallee (CallingConv::C, Type::getVoidTy (*DAG.getContext ()),
DAG.getExternalSymbol (" __sync_synchronize" ,
TLI.getPointerTy (DAG.getDataLayout ())),
std::move (Args), 0 );
std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo (CLI);
Results.push_back (CallResult.second );
break ;
}
// By default, atomic intrinsics are marked Legal and lowered. Targets
// which don't support them directly, however, may want libcalls, in which
// case they mark them Expand, and we get here.
case ISD::ATOMIC_SWAP:
case ISD::ATOMIC_LOAD_ADD:
case ISD::ATOMIC_LOAD_SUB:
case ISD::ATOMIC_LOAD_AND:
case ISD::ATOMIC_LOAD_OR:
case ISD::ATOMIC_LOAD_XOR:
case ISD::ATOMIC_LOAD_NAND:
case ISD::ATOMIC_LOAD_MIN:
case ISD::ATOMIC_LOAD_MAX:
case ISD::ATOMIC_LOAD_UMIN:
case ISD::ATOMIC_LOAD_UMAX:
case ISD::ATOMIC_CMP_SWAP: {
MVT VT = cast<AtomicSDNode>(Node)->getMemoryVT ().getSimpleVT ();
RTLIB::Libcall LC = RTLIB::getATOMIC (Opc, VT);
assert (LC != RTLIB::UNKNOWN_LIBCALL && " Unexpected atomic op or value type!" );
std::pair<SDValue, SDValue> Tmp = ExpandChainLibCall (LC, Node, false );
Results.push_back (Tmp.first );
Results.push_back (Tmp.second );
break ;
}
case ISD::TRAP: {
// If this operation is not supported, lower it to 'abort()' call
TargetLowering::ArgListTy Args;
TargetLowering::CallLoweringInfo CLI (DAG);
CLI.setDebugLoc (dl)
.setChain (Node->getOperand (0 ))
.setCallee (CallingConv::C, Type::getVoidTy (*DAG.getContext ()),
DAG.getExternalSymbol (" abort" ,
TLI.getPointerTy (DAG.getDataLayout ())),
std::move (Args), 0 );
std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo (CLI);
Results.push_back (CallResult.second );
break ;
}
case ISD::FMINNUM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMIN_F32, RTLIB::FMIN_F64,
RTLIB::FMIN_F80, RTLIB::FMIN_F128,
RTLIB::FMIN_PPCF128));
break ;
case ISD::FMAXNUM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMAX_F32, RTLIB::FMAX_F64,
RTLIB::FMAX_F80, RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128));
break ;
case ISD::FSQRT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
RTLIB::SQRT_F80, RTLIB::SQRT_F128,
RTLIB::SQRT_PPCF128));
break ;
case ISD::FSIN:
Results.push_back (ExpandFPLibCall (Node, RTLIB::SIN_F32, RTLIB::SIN_F64,
RTLIB::SIN_F80, RTLIB::SIN_F128,
RTLIB::SIN_PPCF128));
break ;
case ISD::FCOS:
Results.push_back (ExpandFPLibCall (Node, RTLIB::COS_F32, RTLIB::COS_F64,
RTLIB::COS_F80, RTLIB::COS_F128,
RTLIB::COS_PPCF128));
break ;
case ISD::FSINCOS:
// Expand into sincos libcall.
ExpandSinCosLibCall (Node, Results);
break ;
case ISD::FLOG:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
RTLIB::LOG_F80, RTLIB::LOG_F128,
RTLIB::LOG_PPCF128));
break ;
case ISD::FLOG2:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
RTLIB::LOG2_F80, RTLIB::LOG2_F128,
RTLIB::LOG2_PPCF128));
break ;
case ISD::FLOG10:
Results.push_back (ExpandFPLibCall (Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
RTLIB::LOG10_F80, RTLIB::LOG10_F128,
RTLIB::LOG10_PPCF128));
break ;
case ISD::FEXP:
Results.push_back (ExpandFPLibCall (Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
RTLIB::EXP_F80, RTLIB::EXP_F128,
RTLIB::EXP_PPCF128));
break ;
case ISD::FEXP2:
Results.push_back (ExpandFPLibCall (Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
RTLIB::EXP2_F80, RTLIB::EXP2_F128,
RTLIB::EXP2_PPCF128));
break ;
case ISD::FTRUNC:
Results.push_back (ExpandFPLibCall (Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
RTLIB::TRUNC_F80, RTLIB::TRUNC_F128,
RTLIB::TRUNC_PPCF128));
break ;
case ISD::FFLOOR:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64,
RTLIB::FLOOR_F80, RTLIB::FLOOR_F128,
RTLIB::FLOOR_PPCF128));
break ;
case ISD::FCEIL:
Results.push_back (ExpandFPLibCall (Node, RTLIB::CEIL_F32, RTLIB::CEIL_F64,
RTLIB::CEIL_F80, RTLIB::CEIL_F128,
RTLIB::CEIL_PPCF128));
break ;
case ISD::FRINT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::RINT_F32, RTLIB::RINT_F64,
RTLIB::RINT_F80, RTLIB::RINT_F128,
RTLIB::RINT_PPCF128));
break ;
case ISD::FNEARBYINT:
Results.push_back (ExpandFPLibCall (Node, RTLIB::NEARBYINT_F32,
RTLIB::NEARBYINT_F64,
RTLIB::NEARBYINT_F80,
RTLIB::NEARBYINT_F128,
RTLIB::NEARBYINT_PPCF128));
break ;
case ISD::FROUND:
Results.push_back (ExpandFPLibCall (Node, RTLIB::ROUND_F32,
RTLIB::ROUND_F64,
RTLIB::ROUND_F80,
RTLIB::ROUND_F128,
RTLIB::ROUND_PPCF128));
break ;
case ISD::FPOWI:
Results.push_back (ExpandFPLibCall (Node, RTLIB::POWI_F32, RTLIB::POWI_F64,
RTLIB::POWI_F80, RTLIB::POWI_F128,
RTLIB::POWI_PPCF128));
break ;
case ISD::FPOW:
Results.push_back (ExpandFPLibCall (Node, RTLIB::POW_F32, RTLIB::POW_F64,
RTLIB::POW_F80, RTLIB::POW_F128,
RTLIB::POW_PPCF128));
break ;
case ISD::FDIV:
Results.push_back (ExpandFPLibCall (Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
RTLIB::DIV_F80, RTLIB::DIV_F128,
RTLIB::DIV_PPCF128));
break ;
case ISD::FREM:
Results.push_back (ExpandFPLibCall (Node, RTLIB::REM_F32, RTLIB::REM_F64,
RTLIB::REM_F80, RTLIB::REM_F128,
RTLIB::REM_PPCF128));
break ;
case ISD::FMA:
Results.push_back (ExpandFPLibCall (Node, RTLIB::FMA_F32, RTLIB::FMA_F64,
RTLIB::FMA_F80, RTLIB::FMA_F128,
RTLIB::FMA_PPCF128));
break ;
case ISD::FADD:
Results.push_back (ExpandFPLibCall (Node, RTLIB::ADD_F32, RTLIB::ADD_F64,
RTLIB::ADD_F80, RTLIB::ADD_F128,
RTLIB::ADD_PPCF128));
break ;
case ISD::FMUL:
Results.push_back (ExpandFPLibCall (Node, RTLIB::MUL_F32, RTLIB::MUL_F64,
RTLIB::MUL_F80, RTLIB::MUL_F128,
RTLIB::MUL_PPCF128));
break ;
case ISD::FP16_TO_FP:
if (Node->getValueType (0 ) == MVT::f32) {
Results.push_back (ExpandLibCall (RTLIB::FPEXT_F16_F32, Node, false ));
}
break ;
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::FSUB:
Results.push_back (ExpandFPLibCall (Node, RTLIB::SUB_F32, RTLIB::SUB_F64,
RTLIB::SUB_F80, RTLIB::SUB_F128,
RTLIB::SUB_PPCF128));
break ;
case ISD::SREM:
Results.push_back (ExpandIntLibCall (Node, true ,
RTLIB::SREM_I8,
RTLIB::SREM_I16, RTLIB::SREM_I32,
RTLIB::SREM_I64, RTLIB::SREM_I128));
break ;
case ISD::UREM:
Results.push_back (ExpandIntLibCall (Node, false ,
RTLIB::UREM_I8,
RTLIB::UREM_I16, RTLIB::UREM_I32,
RTLIB::UREM_I64, RTLIB::UREM_I128));
break ;
case ISD::SDIV:
Results.push_back (ExpandIntLibCall (Node, true ,
RTLIB::SDIV_I8,
RTLIB::SDIV_I16, RTLIB::SDIV_I32,
RTLIB::SDIV_I64, RTLIB::SDIV_I128));
break ;
case ISD::UDIV:
Results.push_back (ExpandIntLibCall (Node, false ,
RTLIB::UDIV_I8,
RTLIB::UDIV_I16, RTLIB::UDIV_I32,
RTLIB::UDIV_I64, RTLIB::UDIV_I128));
break ;
case ISD::SDIVREM:
case ISD::UDIVREM:
// Expand into divrem libcall
ExpandDivRemLibCall (Node, Results);
break ;
case ISD::MUL:
Results.push_back (ExpandIntLibCall (Node, false ,
RTLIB::MUL_I8,
RTLIB::MUL_I16, RTLIB::MUL_I32,
RTLIB::MUL_I64, RTLIB::MUL_I128));
break ;
}
// Replace the original node with the legalized result.
if (!Results.empty ())
ReplaceNode (Node, Results.data ());
Expand Down