forked from OSchip/llvm-project
[SparcV9] Handle i64 <-> float conversions in sparcv9 mode.
llvm-svn: 193957
This commit is contained in:
parent
91e8f3c348
commit
5ae77f7564
|
@ -949,9 +949,10 @@ static bool isFP128ABICall(const char *CalleeName)
|
||||||
{ "_Q_add", "_Q_sub", "_Q_mul", "_Q_div",
|
{ "_Q_add", "_Q_sub", "_Q_mul", "_Q_div",
|
||||||
"_Q_sqrt", "_Q_neg",
|
"_Q_sqrt", "_Q_neg",
|
||||||
"_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq",
|
"_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq",
|
||||||
|
"_Q_lltoq", "_Q_ulltoq",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
for (const char * const *I = ABICalls; I != 0; ++I)
|
for (const char * const *I = ABICalls; *I != 0; ++I)
|
||||||
if (strcmp(CalleeName, *I) == 0)
|
if (strcmp(CalleeName, *I) == 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1341,7 +1342,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
|
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
||||||
|
|
||||||
// ... nor does SparcV9.
|
// ... nor does SparcV9.
|
||||||
if (Subtarget->is64Bit()) {
|
if (Subtarget->is64Bit()) {
|
||||||
setOperationAction(ISD::UREM, MVT::i64, Expand);
|
setOperationAction(ISD::UREM, MVT::i64, Expand);
|
||||||
|
@ -1353,10 +1354,14 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||||
// Custom expand fp<->sint
|
// Custom expand fp<->sint
|
||||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
|
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
|
||||||
|
|
||||||
// Custom Expand fp<->uint
|
// Custom Expand fp<->uint
|
||||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
|
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
|
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
|
||||||
|
|
||||||
setOperationAction(ISD::BITCAST, MVT::f32, Expand);
|
setOperationAction(ISD::BITCAST, MVT::f32, Expand);
|
||||||
setOperationAction(ISD::BITCAST, MVT::i32, Expand);
|
setOperationAction(ISD::BITCAST, MVT::i32, Expand);
|
||||||
|
@ -1497,6 +1502,14 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||||
setOperationAction(ISD::FNEG, MVT::f128, Custom);
|
setOperationAction(ISD::FNEG, MVT::f128, Custom);
|
||||||
setOperationAction(ISD::FABS, MVT::f128, Custom);
|
setOperationAction(ISD::FABS, MVT::f128, Custom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Subtarget->is64Bit()) {
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Custom legalize f128 operations.
|
// Custom legalize f128 operations.
|
||||||
|
|
||||||
|
@ -1523,6 +1536,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||||
setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
|
setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
|
||||||
setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
|
setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
|
||||||
setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
|
setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox");
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux");
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq");
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq");
|
||||||
setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
|
setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
|
||||||
setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
|
setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
|
||||||
setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
|
setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
|
||||||
|
@ -1537,6 +1554,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||||
setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
|
setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
|
||||||
setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
|
setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
|
||||||
setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
|
setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
|
||||||
setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
|
setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
|
||||||
setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
|
setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
|
||||||
setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
|
setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
|
||||||
|
@ -1564,6 +1585,8 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
case SPISD::Lo: return "SPISD::Lo";
|
case SPISD::Lo: return "SPISD::Lo";
|
||||||
case SPISD::FTOI: return "SPISD::FTOI";
|
case SPISD::FTOI: return "SPISD::FTOI";
|
||||||
case SPISD::ITOF: return "SPISD::ITOF";
|
case SPISD::ITOF: return "SPISD::ITOF";
|
||||||
|
case SPISD::FTOX: return "SPISD::FTOX";
|
||||||
|
case SPISD::XTOF: return "SPISD::XTOF";
|
||||||
case SPISD::CALL: return "SPISD::CALL";
|
case SPISD::CALL: return "SPISD::CALL";
|
||||||
case SPISD::RET_FLAG: return "SPISD::RET_FLAG";
|
case SPISD::RET_FLAG: return "SPISD::RET_FLAG";
|
||||||
case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
|
case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
|
||||||
|
@ -2055,59 +2078,97 @@ static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
|
||||||
const SparcTargetLowering &TLI,
|
const SparcTargetLowering &TLI,
|
||||||
bool hasHardQuad) {
|
bool hasHardQuad) {
|
||||||
SDLoc dl(Op);
|
SDLoc dl(Op);
|
||||||
// Convert the fp value to integer in an FP register.
|
EVT VT = Op.getValueType();
|
||||||
assert(Op.getValueType() == MVT::i32);
|
assert(VT == MVT::i32 || VT == MVT::i64);
|
||||||
|
|
||||||
if (Op.getOperand(0).getValueType() == MVT::f128 && !hasHardQuad)
|
// Expand f128 operations to fp128 abi calls.
|
||||||
return TLI.LowerF128Op(Op, DAG,
|
if (Op.getOperand(0).getValueType() == MVT::f128
|
||||||
TLI.getLibcallName(RTLIB::FPTOSINT_F128_I32), 1);
|
&& (!hasHardQuad || !TLI.isTypeLegal(VT))) {
|
||||||
|
const char *libName = TLI.getLibcallName(VT == MVT::i32
|
||||||
|
? RTLIB::FPTOSINT_F128_I32
|
||||||
|
: RTLIB::FPTOSINT_F128_I64);
|
||||||
|
return TLI.LowerF128Op(Op, DAG, libName, 1);
|
||||||
|
}
|
||||||
|
|
||||||
Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0));
|
// Expand if the resulting type is illegal.
|
||||||
return DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op);
|
if (!TLI.isTypeLegal(VT))
|
||||||
|
return SDValue(0, 0);
|
||||||
|
|
||||||
|
// Otherwise, Convert the fp value to integer in an FP register.
|
||||||
|
if (VT == MVT::i32)
|
||||||
|
Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0));
|
||||||
|
else
|
||||||
|
Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0));
|
||||||
|
|
||||||
|
return DAG.getNode(ISD::BITCAST, dl, VT, Op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG,
|
static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG,
|
||||||
const SparcTargetLowering &TLI,
|
const SparcTargetLowering &TLI,
|
||||||
bool hasHardQuad) {
|
bool hasHardQuad) {
|
||||||
SDLoc dl(Op);
|
SDLoc dl(Op);
|
||||||
assert(Op.getOperand(0).getValueType() == MVT::i32);
|
EVT OpVT = Op.getOperand(0).getValueType();
|
||||||
SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Op.getOperand(0));
|
assert(OpVT == MVT::i32 || (OpVT == MVT::i64));
|
||||||
// Convert the int value to FP in an FP register.
|
|
||||||
if (Op.getValueType() == MVT::f128 && !hasHardQuad)
|
EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64;
|
||||||
return TLI.LowerF128Op(Op, DAG,
|
|
||||||
TLI.getLibcallName(RTLIB::SINTTOFP_I32_F128), 1);
|
// Expand f128 operations to fp128 ABI calls.
|
||||||
return DAG.getNode(SPISD::ITOF, dl, Op.getValueType(), Tmp);
|
if (Op.getValueType() == MVT::f128
|
||||||
|
&& (!hasHardQuad || !TLI.isTypeLegal(OpVT))) {
|
||||||
|
const char *libName = TLI.getLibcallName(OpVT == MVT::i32
|
||||||
|
? RTLIB::SINTTOFP_I32_F128
|
||||||
|
: RTLIB::SINTTOFP_I64_F128);
|
||||||
|
return TLI.LowerF128Op(Op, DAG, libName, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand if the operand type is illegal.
|
||||||
|
if (!TLI.isTypeLegal(OpVT))
|
||||||
|
return SDValue(0, 0);
|
||||||
|
|
||||||
|
// Otherwise, Convert the int value to FP in an FP register.
|
||||||
|
SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0));
|
||||||
|
unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF;
|
||||||
|
return DAG.getNode(opcode, dl, Op.getValueType(), Tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG,
|
static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG,
|
||||||
const SparcTargetLowering &TLI,
|
const SparcTargetLowering &TLI,
|
||||||
bool hasHardQuad) {
|
bool hasHardQuad) {
|
||||||
|
SDLoc dl(Op);
|
||||||
|
EVT VT = Op.getValueType();
|
||||||
|
|
||||||
// Expand if it does not involve f128 or the target has support for
|
// Expand if it does not involve f128 or the target has support for
|
||||||
// quad floating point instructions.
|
// quad floating point instructions and the resulting type is legal.
|
||||||
if (Op.getOperand(0).getValueType() != MVT::f128 || hasHardQuad)
|
if (Op.getOperand(0).getValueType() != MVT::f128 ||
|
||||||
|
(hasHardQuad && TLI.isTypeLegal(VT)))
|
||||||
return SDValue(0, 0);
|
return SDValue(0, 0);
|
||||||
|
|
||||||
SDLoc dl(Op);
|
assert(VT == MVT::i32 || VT == MVT::i64);
|
||||||
assert(Op.getValueType() == MVT::i32);
|
|
||||||
|
|
||||||
return TLI.LowerF128Op(Op, DAG,
|
return TLI.LowerF128Op(Op, DAG,
|
||||||
TLI.getLibcallName(RTLIB::FPTOUINT_F128_I32), 1);
|
TLI.getLibcallName(VT == MVT::i32
|
||||||
|
? RTLIB::FPTOUINT_F128_I32
|
||||||
|
: RTLIB::FPTOUINT_F128_I64),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
|
static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
|
||||||
const SparcTargetLowering &TLI,
|
const SparcTargetLowering &TLI,
|
||||||
bool hasHardQuad) {
|
bool hasHardQuad) {
|
||||||
|
SDLoc dl(Op);
|
||||||
|
EVT OpVT = Op.getOperand(0).getValueType();
|
||||||
|
assert(OpVT == MVT::i32 || OpVT == MVT::i64);
|
||||||
|
|
||||||
// Expand if it does not involve f128 or the target has support for
|
// Expand if it does not involve f128 or the target has support for
|
||||||
// quad floating point instructions.
|
// quad floating point instructions and the operand type is legal.
|
||||||
if (Op.getValueType() != MVT::f128 || hasHardQuad)
|
if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT)))
|
||||||
return SDValue(0, 0);
|
return SDValue(0, 0);
|
||||||
|
|
||||||
SDLoc dl(Op);
|
|
||||||
assert(Op.getOperand(0).getValueType() == MVT::i32);
|
|
||||||
|
|
||||||
return TLI.LowerF128Op(Op, DAG,
|
return TLI.LowerF128Op(Op, DAG,
|
||||||
TLI.getLibcallName(RTLIB::UINTTOFP_I32_F128), 1);
|
TLI.getLibcallName(OpVT == MVT::i32
|
||||||
|
? RTLIB::UINTTOFP_I32_F128
|
||||||
|
: RTLIB::UINTTOFP_I64_F128),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
|
static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
|
||||||
|
@ -2702,3 +2763,50 @@ SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
||||||
// The Sparc target isn't yet aware of offsets.
|
// The Sparc target isn't yet aware of offsets.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>& Results,
|
||||||
|
SelectionDAG &DAG) const {
|
||||||
|
|
||||||
|
SDLoc dl(N);
|
||||||
|
|
||||||
|
RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL;
|
||||||
|
|
||||||
|
switch (N->getOpcode()) {
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Do not know how to custom type legalize this operation!");
|
||||||
|
|
||||||
|
case ISD::FP_TO_SINT:
|
||||||
|
case ISD::FP_TO_UINT:
|
||||||
|
// Custom lower only if it involves f128 or i64.
|
||||||
|
if (N->getOperand(0).getValueType() != MVT::f128
|
||||||
|
|| N->getValueType(0) != MVT::i64)
|
||||||
|
return;
|
||||||
|
libCall = ((N->getOpcode() == ISD::FP_TO_SINT)
|
||||||
|
? RTLIB::FPTOSINT_F128_I64
|
||||||
|
: RTLIB::FPTOUINT_F128_I64);
|
||||||
|
|
||||||
|
Results.push_back(LowerF128Op(SDValue(N, 0),
|
||||||
|
DAG,
|
||||||
|
getLibcallName(libCall),
|
||||||
|
1));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ISD::SINT_TO_FP:
|
||||||
|
case ISD::UINT_TO_FP:
|
||||||
|
// Custom lower only if it involves f128 or i64.
|
||||||
|
if (N->getValueType(0) != MVT::f128
|
||||||
|
|| N->getOperand(0).getValueType() != MVT::i64)
|
||||||
|
return;
|
||||||
|
|
||||||
|
libCall = ((N->getOpcode() == ISD::SINT_TO_FP)
|
||||||
|
? RTLIB::SINTTOFP_I64_F128
|
||||||
|
: RTLIB::UINTTOFP_I64_F128);
|
||||||
|
|
||||||
|
Results.push_back(LowerF128Op(SDValue(N, 0),
|
||||||
|
DAG,
|
||||||
|
getLibcallName(libCall),
|
||||||
|
1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace llvm {
|
||||||
|
|
||||||
FTOI, // FP to Int within a FP register.
|
FTOI, // FP to Int within a FP register.
|
||||||
ITOF, // Int to FP within a FP register.
|
ITOF, // Int to FP within a FP register.
|
||||||
|
FTOX, // FP to Int64 within a FP register.
|
||||||
|
XTOF, // Int64 to FP within a FP register.
|
||||||
|
|
||||||
CALL, // A call instruction.
|
CALL, // A call instruction.
|
||||||
RET_FLAG, // Return with a flag operand.
|
RET_FLAG, // Return with a flag operand.
|
||||||
|
@ -149,6 +151,10 @@ namespace llvm {
|
||||||
// (ldd, call _Q_fdtoq) is more expensive than two ldds.
|
// (ldd, call _Q_fdtoq) is more expensive than two ldds.
|
||||||
return VT != MVT::f128;
|
return VT != MVT::f128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>& Results,
|
||||||
|
SelectionDAG &DAG) const;
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
|
|
@ -344,6 +344,42 @@ def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd),
|
||||||
(SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>;
|
(SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>;
|
||||||
} // Uses, Constraints
|
} // Uses, Constraints
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// 64-bit Floating Point Conversions.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
let Predicates = [Is64Bit] in {
|
||||||
|
|
||||||
|
def FXTOS : F3_3u<2, 0b110100, 0b010000100,
|
||||||
|
(outs FPRegs:$dst), (ins DFPRegs:$src),
|
||||||
|
"fxtos $src, $dst",
|
||||||
|
[(set FPRegs:$dst, (SPxtof DFPRegs:$src))]>;
|
||||||
|
def FXTOD : F3_3u<2, 0b110100, 0b010001000,
|
||||||
|
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||||
|
"fxtod $src, $dst",
|
||||||
|
[(set DFPRegs:$dst, (SPxtof DFPRegs:$src))]>;
|
||||||
|
def FXTOQ : F3_3u<2, 0b110100, 0b010001100,
|
||||||
|
(outs QFPRegs:$dst), (ins DFPRegs:$src),
|
||||||
|
"fxtoq $src, $dst",
|
||||||
|
[(set QFPRegs:$dst, (SPxtof DFPRegs:$src))]>,
|
||||||
|
Requires<[HasHardQuad]>;
|
||||||
|
|
||||||
|
def FSTOX : F3_3u<2, 0b110100, 0b010000001,
|
||||||
|
(outs DFPRegs:$dst), (ins FPRegs:$src),
|
||||||
|
"fstox $src, $dst",
|
||||||
|
[(set DFPRegs:$dst, (SPftox FPRegs:$src))]>;
|
||||||
|
def FDTOX : F3_3u<2, 0b110100, 0b010000010,
|
||||||
|
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||||
|
"fdtox $src, $dst",
|
||||||
|
[(set DFPRegs:$dst, (SPftox DFPRegs:$src))]>;
|
||||||
|
def FQTOX : F3_3u<2, 0b110100, 0b010000011,
|
||||||
|
(outs DFPRegs:$dst), (ins QFPRegs:$src),
|
||||||
|
"fqtox $src, $dst",
|
||||||
|
[(set DFPRegs:$dst, (SPftox QFPRegs:$src))]>,
|
||||||
|
Requires<[HasHardQuad]>;
|
||||||
|
|
||||||
|
} // Predicates = [Is64Bit]
|
||||||
|
|
||||||
def : Pat<(SPselectxcc i64:$t, i64:$f, imm:$cond),
|
def : Pat<(SPselectxcc i64:$t, i64:$f, imm:$cond),
|
||||||
(MOVXCCrr $t, $f, imm:$cond)>;
|
(MOVXCCrr $t, $f, imm:$cond)>;
|
||||||
def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond),
|
def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond),
|
||||||
|
|
|
@ -107,6 +107,10 @@ def SDTSPFTOI :
|
||||||
SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
|
SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
|
||||||
def SDTSPITOF :
|
def SDTSPITOF :
|
||||||
SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>;
|
SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>;
|
||||||
|
def SDTSPFTOX :
|
||||||
|
SDTypeProfile<1, 1, [SDTCisVT<0, f64>, SDTCisFP<1>]>;
|
||||||
|
def SDTSPXTOF :
|
||||||
|
SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f64>]>;
|
||||||
|
|
||||||
def SDTSPtlsadd :
|
def SDTSPtlsadd :
|
||||||
SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
|
SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
|
||||||
|
@ -124,6 +128,8 @@ def SPlo : SDNode<"SPISD::Lo", SDTIntUnaryOp>;
|
||||||
|
|
||||||
def SPftoi : SDNode<"SPISD::FTOI", SDTSPFTOI>;
|
def SPftoi : SDNode<"SPISD::FTOI", SDTSPFTOI>;
|
||||||
def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>;
|
def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>;
|
||||||
|
def SPftox : SDNode<"SPISD::FTOX", SDTSPFTOX>;
|
||||||
|
def SPxtof : SDNode<"SPISD::XTOF", SDTSPXTOF>;
|
||||||
|
|
||||||
def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>;
|
def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>;
|
||||||
def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>;
|
def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8
|
; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8
|
||||||
; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT
|
; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT
|
||||||
; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
|
; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
|
||||||
|
; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s -check-prefix=SPARC64
|
||||||
|
|
||||||
; V8-LABEL: test_neg:
|
; V8-LABEL: test_neg:
|
||||||
; V8: call get_double
|
; V8: call get_double
|
||||||
|
@ -16,6 +16,9 @@
|
||||||
; V9-LABEL: test_neg:
|
; V9-LABEL: test_neg:
|
||||||
; V9: fnegd %f0, %f0
|
; V9: fnegd %f0, %f0
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_neg:
|
||||||
|
; SPARC64: fnegd %f0, %f0
|
||||||
|
|
||||||
define double @test_neg() {
|
define double @test_neg() {
|
||||||
entry:
|
entry:
|
||||||
%0 = tail call double @get_double()
|
%0 = tail call double @get_double()
|
||||||
|
@ -35,6 +38,10 @@ entry:
|
||||||
; V9-LABEL: test_abs:
|
; V9-LABEL: test_abs:
|
||||||
; V9: fabsd %f0, %f0
|
; V9: fabsd %f0, %f0
|
||||||
|
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_abs:
|
||||||
|
; SPARC64: fabsd %f0, %f0
|
||||||
|
|
||||||
define double @test_abs() {
|
define double @test_abs() {
|
||||||
entry:
|
entry:
|
||||||
%0 = tail call double @get_double()
|
%0 = tail call double @get_double()
|
||||||
|
@ -56,6 +63,10 @@ declare double @llvm.fabs.f64(double) nounwind readonly
|
||||||
; V9: faddd {{.+}}, {{.+}}, [[R:%f((3(2|4|6|8))|((4|5)(0|2|4|6|8))|(60|62))]]
|
; V9: faddd {{.+}}, {{.+}}, [[R:%f((3(2|4|6|8))|((4|5)(0|2|4|6|8))|(60|62))]]
|
||||||
; V9: fmovd [[R]], %f0
|
; V9: fmovd [[R]], %f0
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_v9_floatreg:
|
||||||
|
; SPARC64: fsubd {{.+}}, {{.+}}, {{.+}}
|
||||||
|
; SPARC64: faddd {{.+}}, {{.+}}, [[R:%f((3(2|4|6|8))|((4|5)(0|2|4|6|8))|(60|62))]]
|
||||||
|
; SPARC64: fmovd [[R]], %f0
|
||||||
|
|
||||||
define double @test_v9_floatreg() {
|
define double @test_v9_floatreg() {
|
||||||
entry:
|
entry:
|
||||||
|
@ -67,4 +78,172 @@ entry:
|
||||||
ret double %3
|
ret double %3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_xtos_stox
|
||||||
|
; V8: call __floatdisf
|
||||||
|
; V8: call __fixsfdi
|
||||||
|
|
||||||
|
; V9-LABEL: test_xtos_stox
|
||||||
|
; V9: call __floatdisf
|
||||||
|
; V9: call __fixsfdi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_xtos_stox
|
||||||
|
; SPARC64: fxtos
|
||||||
|
; SPARC64: fstox
|
||||||
|
|
||||||
|
define void @test_xtos_stox(i64 %a, i64* %ptr0, float* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = sitofp i64 %a to float
|
||||||
|
store float %0, float* %ptr1, align 8
|
||||||
|
%1 = fptosi float %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_itos_stoi
|
||||||
|
; V8: fitos
|
||||||
|
; V8: fstoi
|
||||||
|
|
||||||
|
; V9-LABEL: test_itos_stoi
|
||||||
|
; V9: fitos
|
||||||
|
; V9: fstoi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_itos_stoi
|
||||||
|
; SPARC64: fitos
|
||||||
|
; SPARC64: fstoi
|
||||||
|
|
||||||
|
define void @test_itos_stoi(i32 %a, i32* %ptr0, float* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = sitofp i32 %a to float
|
||||||
|
store float %0, float* %ptr1, align 8
|
||||||
|
%1 = fptosi float %0 to i32
|
||||||
|
store i32 %1, i32* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; V8-LABEL: test_xtod_dtox
|
||||||
|
; V8: call __floatdidf
|
||||||
|
; V8: call __fixdfdi
|
||||||
|
|
||||||
|
; V9-LABEL: test_xtod_dtox
|
||||||
|
; V9: call __floatdidf
|
||||||
|
; V9: call __fixdfdi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_xtod_dtox
|
||||||
|
; SPARC64: fxtod
|
||||||
|
; SPARC64: fdtox
|
||||||
|
|
||||||
|
define void @test_xtod_dtox(i64 %a, i64* %ptr0, double* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = sitofp i64 %a to double
|
||||||
|
store double %0, double* %ptr1, align 8
|
||||||
|
%1 = fptosi double %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_itod_dtoi
|
||||||
|
; V8: fitod
|
||||||
|
; V8: fdtoi
|
||||||
|
|
||||||
|
; V9-LABEL: test_itod_dtoi
|
||||||
|
; V9: fitod
|
||||||
|
; V9: fdtoi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_itod_dtoi
|
||||||
|
; SPARC64: fitod
|
||||||
|
; SPARC64: fdtoi
|
||||||
|
|
||||||
|
define void @test_itod_dtoi(i32 %a, i32* %ptr0, double* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = sitofp i32 %a to double
|
||||||
|
store double %0, double* %ptr1, align 8
|
||||||
|
%1 = fptosi double %0 to i32
|
||||||
|
store i32 %1, i32* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_uxtos_stoux
|
||||||
|
; V8: call __floatundisf
|
||||||
|
; V8: call __fixunssfdi
|
||||||
|
|
||||||
|
; V9-LABEL: test_uxtos_stoux
|
||||||
|
; V9: call __floatundisf
|
||||||
|
; V9: call __fixunssfdi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_uxtos_stoux
|
||||||
|
; SPARC64-NOT: call __floatundisf
|
||||||
|
; SPARC64-NOT: call __fixunssfdi
|
||||||
|
|
||||||
|
define void @test_uxtos_stoux(i64 %a, i64* %ptr0, float* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = uitofp i64 %a to float
|
||||||
|
store float %0, float* %ptr1, align 8
|
||||||
|
%1 = fptoui float %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_utos_stou
|
||||||
|
; V8: fdtos
|
||||||
|
; V8: fstoi
|
||||||
|
|
||||||
|
; V9-LABEL: test_utos_stou
|
||||||
|
; V9: fdtos
|
||||||
|
; V9: fstoi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_utos_stou
|
||||||
|
; SPARC64: fdtos
|
||||||
|
; SPARC64: fstoi
|
||||||
|
|
||||||
|
define void @test_utos_stou(i32 %a, i32* %ptr0, float* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = uitofp i32 %a to float
|
||||||
|
store float %0, float* %ptr1, align 8
|
||||||
|
%1 = fptoui float %0 to i32
|
||||||
|
store i32 %1, i32* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; V8-LABEL: test_uxtod_dtoux
|
||||||
|
; V8: call __floatundidf
|
||||||
|
; V8: call __fixunsdfdi
|
||||||
|
|
||||||
|
; V9-LABEL: test_uxtod_dtoux
|
||||||
|
; V9: call __floatundidf
|
||||||
|
; V9: call __fixunsdfdi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_uxtod_dtoux
|
||||||
|
; SPARC64-NOT: call __floatundidf
|
||||||
|
; SPARC64-NOT: call __floatunsdfdi
|
||||||
|
|
||||||
|
define void @test_uxtod_dtoux(i64 %a, i64* %ptr0, double* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = uitofp i64 %a to double
|
||||||
|
store double %0, double* %ptr1, align 8
|
||||||
|
%1 = fptoui double %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; V8-LABEL: test_utod_dtou
|
||||||
|
; V8-NOT: fitod
|
||||||
|
; V8: fdtoi
|
||||||
|
|
||||||
|
; V9-LABEL: test_utod_dtou
|
||||||
|
; V9-NOT: fitod
|
||||||
|
; V9: fdtoi
|
||||||
|
|
||||||
|
; SPARC64-LABEL: test_utod_dtou
|
||||||
|
; SPARC64-NOT: fitod
|
||||||
|
; SPARC64: fdtoi
|
||||||
|
|
||||||
|
define void @test_utod_dtou(i32 %a, double %b, i32* %ptr0, double* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = uitofp i32 %a to double
|
||||||
|
store double %0, double* %ptr1, align 8
|
||||||
|
%1 = fptoui double %b to i32
|
||||||
|
store i32 %1, i32* %ptr0, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
@ -180,3 +180,55 @@ entry:
|
||||||
%4 = add i32 %2, %3
|
%4 = add i32 %2, %3
|
||||||
ret i32 %4
|
ret i32 %4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; HARD-LABEL: test_itoq_qtoi
|
||||||
|
; HARD: call _Q_lltoq
|
||||||
|
; HARD: call _Q_qtoll
|
||||||
|
; HARD: fitoq
|
||||||
|
; HARD: fqtoi
|
||||||
|
|
||||||
|
; SOFT-LABEL: test_itoq_qtoi
|
||||||
|
; SOFT: call _Q_lltoq
|
||||||
|
; SOFT: call _Q_qtoll
|
||||||
|
; SOFT: call _Q_itoq
|
||||||
|
; SOFT: call _Q_qtoi
|
||||||
|
|
||||||
|
define void @test_itoq_qtoi(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = sitofp i64 %a to fp128
|
||||||
|
store fp128 %0, fp128* %ptr1, align 8
|
||||||
|
%1 = fptosi fp128 %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
%2 = sitofp i32 %b to fp128
|
||||||
|
store fp128 %2, fp128* %ptr1, align 8
|
||||||
|
%3 = fptosi fp128 %2 to i32
|
||||||
|
%4 = bitcast i64* %ptr0 to i32*
|
||||||
|
store i32 %3, i32* %4, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; HARD-LABEL: test_utoq_qtou
|
||||||
|
; HARD-DAG: call _Q_ulltoq
|
||||||
|
; HARD-DAG: call _Q_qtoull
|
||||||
|
; HARD-DAG: fdtoq
|
||||||
|
; HARD-DAG: fqtoi
|
||||||
|
|
||||||
|
; SOFT-LABEL: test_utoq_qtou
|
||||||
|
; SOFT-DAG: call _Q_ulltoq
|
||||||
|
; SOFT-DAG: call _Q_qtoull
|
||||||
|
; SOFT-DAG: call _Q_utoq
|
||||||
|
; SOFT-DAG: call _Q_qtou
|
||||||
|
|
||||||
|
define void @test_utoq_qtou(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) {
|
||||||
|
entry:
|
||||||
|
%0 = uitofp i64 %a to fp128
|
||||||
|
store fp128 %0, fp128* %ptr1, align 8
|
||||||
|
%1 = fptoui fp128 %0 to i64
|
||||||
|
store i64 %1, i64* %ptr0, align 8
|
||||||
|
%2 = uitofp i32 %b to fp128
|
||||||
|
store fp128 %2, fp128* %ptr1, align 8
|
||||||
|
%3 = fptoui fp128 %2 to i32
|
||||||
|
%4 = bitcast i64* %ptr0 to i32*
|
||||||
|
store i32 %3, i32* %4, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue