[SparcV9] Handle i64 <-> float conversions in sparcv9 mode.

llvm-svn: 193957
This commit is contained in:
Venkatraman Govindaraju 2013-11-03 12:28:40 +00:00
parent 91e8f3c348
commit 5ae77f7564
6 changed files with 416 additions and 29 deletions

View File

@ -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;
}
}

View File

@ -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

View File

@ -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),

View File

@ -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]>;

View File

@ -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
}

View File

@ -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
}