From 5ae77f7564eae945c1fdfb28f1c38d41146e3680 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sun, 3 Nov 2013 12:28:40 +0000 Subject: [PATCH] [SparcV9] Handle i64 <-> float conversions in sparcv9 mode. llvm-svn: 193957 --- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 164 +++++++++++++++--- llvm/lib/Target/Sparc/SparcISelLowering.h | 6 + llvm/lib/Target/Sparc/SparcInstr64Bit.td | 36 ++++ llvm/lib/Target/Sparc/SparcInstrInfo.td | 6 + llvm/test/CodeGen/SPARC/float.ll | 181 +++++++++++++++++++- llvm/test/CodeGen/SPARC/fp128.ll | 52 ++++++ 6 files changed, 416 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index bdee86427435..fe5c7cb372ee 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -949,9 +949,10 @@ static bool isFP128ABICall(const char *CalleeName) { "_Q_add", "_Q_sub", "_Q_mul", "_Q_div", "_Q_sqrt", "_Q_neg", "_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq", + "_Q_lltoq", "_Q_ulltoq", 0 }; - for (const char * const *I = ABICalls; I != 0; ++I) + for (const char * const *I = ABICalls; *I != 0; ++I) if (strcmp(CalleeName, *I) == 0) return true; return false; @@ -1341,7 +1342,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setOperationAction(ISD::SREM, MVT::i32, Expand); setOperationAction(ISD::SDIVREM, MVT::i32, Expand); setOperationAction(ISD::UDIVREM, MVT::i32, Expand); - + // ... nor does SparcV9. if (Subtarget->is64Bit()) { setOperationAction(ISD::UREM, MVT::i64, Expand); @@ -1353,10 +1354,14 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) // Custom expand fp<->sint setOperationAction(ISD::FP_TO_SINT, 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 setOperationAction(ISD::FP_TO_UINT, 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::i32, Expand); @@ -1497,6 +1502,14 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setOperationAction(ISD::FNEG, 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 { // Custom legalize f128 operations. @@ -1523,6 +1536,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui"); setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq"); 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_F64_F128, "_Qp_dtoq"); setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos"); @@ -1537,6 +1554,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou"); setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq"); 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_F64_F128, "_Q_dtoq"); 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::FTOI: return "SPISD::FTOI"; 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::RET_FLAG: return "SPISD::RET_FLAG"; 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, bool hasHardQuad) { SDLoc dl(Op); - // Convert the fp value to integer in an FP register. - assert(Op.getValueType() == MVT::i32); + EVT VT = Op.getValueType(); + assert(VT == MVT::i32 || VT == MVT::i64); - if (Op.getOperand(0).getValueType() == MVT::f128 && !hasHardQuad) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::FPTOSINT_F128_I32), 1); + // Expand f128 operations to fp128 abi calls. + if (Op.getOperand(0).getValueType() == MVT::f128 + && (!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)); - return DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); + // Expand if the resulting type is illegal. + 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, const SparcTargetLowering &TLI, bool hasHardQuad) { SDLoc dl(Op); - assert(Op.getOperand(0).getValueType() == MVT::i32); - SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Op.getOperand(0)); - // Convert the int value to FP in an FP register. - if (Op.getValueType() == MVT::f128 && !hasHardQuad) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::SINTTOFP_I32_F128), 1); - return DAG.getNode(SPISD::ITOF, dl, Op.getValueType(), Tmp); + EVT OpVT = Op.getOperand(0).getValueType(); + assert(OpVT == MVT::i32 || (OpVT == MVT::i64)); + + EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64; + + // Expand f128 operations to fp128 ABI calls. + 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, const SparcTargetLowering &TLI, bool hasHardQuad) { + SDLoc dl(Op); + EVT VT = Op.getValueType(); + // Expand if it does not involve f128 or the target has support for - // quad floating point instructions. - if (Op.getOperand(0).getValueType() != MVT::f128 || hasHardQuad) + // quad floating point instructions and the resulting type is legal. + if (Op.getOperand(0).getValueType() != MVT::f128 || + (hasHardQuad && TLI.isTypeLegal(VT))) return SDValue(0, 0); - SDLoc dl(Op); - assert(Op.getValueType() == MVT::i32); + assert(VT == MVT::i32 || VT == MVT::i64); 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, const SparcTargetLowering &TLI, 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 - // quad floating point instructions. - if (Op.getValueType() != MVT::f128 || hasHardQuad) + // quad floating point instructions and the operand type is legal. + if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT))) return SDValue(0, 0); - SDLoc dl(Op); - assert(Op.getOperand(0).getValueType() == MVT::i32); - 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, @@ -2702,3 +2763,50 @@ SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Sparc target isn't yet aware of offsets. return false; } + +void SparcTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl& 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; + } +} diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 57ef0995e71c..8d27caaf159b 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -37,6 +37,8 @@ namespace llvm { FTOI, // FP to Int 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. RET_FLAG, // Return with a flag operand. @@ -149,6 +151,10 @@ namespace llvm { // (ldd, call _Q_fdtoq) is more expensive than two ldds. return VT != MVT::f128; } + + virtual void ReplaceNodeResults(SDNode *N, + SmallVectorImpl& Results, + SelectionDAG &DAG) const; }; } // end namespace llvm diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index cf8747d0900a..51397d8fb319 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -344,6 +344,42 @@ def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd), (SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>; } // 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), (MOVXCCrr $t, $f, imm:$cond)>; def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond), diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index b8628b928fa6..8dadc89fb907 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -107,6 +107,10 @@ def SDTSPFTOI : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; def SDTSPITOF : 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 : 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 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 SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>; diff --git a/llvm/test/CodeGen/SPARC/float.ll b/llvm/test/CodeGen/SPARC/float.ll index ca9c40dfd65b..66367042cad9 100644 --- a/llvm/test/CodeGen/SPARC/float.ll +++ b/llvm/test/CodeGen/SPARC/float.ll @@ -1,7 +1,7 @@ ; 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 -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: call get_double @@ -16,6 +16,9 @@ ; V9-LABEL: test_neg: ; V9: fnegd %f0, %f0 +; SPARC64-LABEL: test_neg: +; SPARC64: fnegd %f0, %f0 + define double @test_neg() { entry: %0 = tail call double @get_double() @@ -35,6 +38,10 @@ entry: ; V9-LABEL: test_abs: ; V9: fabsd %f0, %f0 + +; SPARC64-LABEL: test_abs: +; SPARC64: fabsd %f0, %f0 + define double @test_abs() { entry: %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: 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() { entry: @@ -67,4 +78,172 @@ entry: 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 +} diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index 8049dbe98c40..c761361e773e 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -180,3 +180,55 @@ entry: %4 = add i32 %2, %3 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 +}