diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -457,6 +457,12 @@ /// have an extra operand for chain. STRICT_MFVSR = ISD::FIRST_TARGET_STRICTFP_OPCODE, + /// Constrained integer-to-floating-point conversion instructions. + STRICT_FCFID, + STRICT_FCFIDU, + STRICT_FCFIDS, + STRICT_FCFIDUS, + /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a /// byte-swapping store instruction. It byte-swaps the low "Type" bits of /// the GPRC input, then stores it through Ptr. Type can be either i16 or diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -215,6 +215,13 @@ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); if (isPPC64 || Subtarget.hasFPCVT()) { + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i1, Promote); + AddPromotedToType(ISD::STRICT_SINT_TO_FP, MVT::i1, + isPPC64 ? MVT::i64 : MVT::i32); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i1, Promote); + AddPromotedToType(ISD::STRICT_UINT_TO_FP, MVT::i1, + isPPC64 ? MVT::i64 : MVT::i32); + setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote); AddPromotedToType (ISD::SINT_TO_FP, MVT::i1, isPPC64 ? MVT::i64 : MVT::i32); @@ -222,6 +229,8 @@ AddPromotedToType(ISD::UINT_TO_FP, MVT::i1, isPPC64 ? MVT::i64 : MVT::i32); } else { + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i1, Custom); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i1, Custom); setOperationAction(ISD::SINT_TO_FP, MVT::i1, Custom); setOperationAction(ISD::UINT_TO_FP, MVT::i1, Custom); } @@ -435,6 +444,8 @@ setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); // PowerPC does not have [U|S]INT_TO_FP + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Expand); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i32, Expand); setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); } @@ -566,6 +577,8 @@ // They also have instructions for converting between i64 and fp. setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i64, Custom); setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i64, Expand); + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i64, Custom); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i64, Expand); setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); @@ -575,8 +588,10 @@ setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom); setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); - if (Subtarget.hasLFIWAX() || Subtarget.isPPC64()) + if (Subtarget.hasLFIWAX() || Subtarget.isPPC64()) { setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Custom); + } } else { // PowerPC does not have FP_TO_UINT on 32-bit implementations. if (Subtarget.hasSPE()) { @@ -593,6 +608,8 @@ if (Subtarget.has64BitSupport()) { setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i64, Custom); setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i64, Custom); + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i64, Custom); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i64, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom); setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); @@ -601,6 +618,8 @@ setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom); + setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i32, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); @@ -1588,6 +1607,14 @@ case PPCISD::FNMSUB: return "PPCISD::FNMSUB"; case PPCISD::STRICT_MFVSR: return "PPCISD::STRICT_MFVSR"; + case PPCISD::STRICT_FCFID: + return "PPCISD::STRICT_FCFID"; + case PPCISD::STRICT_FCFIDU: + return "PPCISD::STRICT_FCFIDU"; + case PPCISD::STRICT_FCFIDS: + return "PPCISD::STRICT_FCFIDS"; + case PPCISD::STRICT_FCFIDUS: + return "PPCISD::STRICT_FCFIDUS"; } return nullptr; } @@ -8458,16 +8485,36 @@ continue; if (UI->getOpcode() != ISD::SINT_TO_FP && - UI->getOpcode() != ISD::UINT_TO_FP) + UI->getOpcode() != ISD::UINT_TO_FP && + UI->getOpcode() != ISD::STRICT_SINT_TO_FP && + UI->getOpcode() != ISD::STRICT_UINT_TO_FP) return true; } return false; } +static unsigned getPPCStrictOpcode(unsigned Opc) { + switch (Opc) { + default: + llvm_unreachable("No strict version of this opcode!"); + case PPCISD::MFVSR: + return PPCISD::STRICT_MFVSR; + case PPCISD::FCFID: + return PPCISD::STRICT_FCFID; + case PPCISD::FCFIDU: + return PPCISD::STRICT_FCFIDU; + case PPCISD::FCFIDS: + return PPCISD::STRICT_FCFIDS; + case PPCISD::FCFIDUS: + return PPCISD::STRICT_FCFIDUS; + } +} + static SDValue convertIntToFP(SDValue Op, SDValue Src, SelectionDAG &DAG, const PPCSubtarget &Subtarget) { - bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP; + bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP || + Op.getOpcode() == ISD::STRICT_SINT_TO_FP; SDLoc dl(Op); // If we have FCFIDS, then use it when converting to single-precision. // Otherwise, convert to double-precision and then round. @@ -8475,7 +8522,11 @@ unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS) : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU); EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64; - return DAG.getNode(ConvOpc, dl, ConvTy, Src); + if (Op->isStrictFPOpcode()) + return DAG.getNode(getPPCStrictOpcode(ConvOpc), dl, {ConvTy, MVT::Other}, + {Op.getOperand(0), Src}); + else + return DAG.getNode(ConvOpc, dl, ConvTy, Src); } /// Custom lowers integer to floating point conversions to use @@ -8489,9 +8540,10 @@ "Invalid floating point type as target of conversion"); assert(Subtarget.hasFPCVT() && "Int to FP conversions with direct moves require FPCVT"); - SDValue Src = Op.getOperand(0); + SDValue Src = Op.getOperand(Op->isStrictFPOpcode() ? 1 : 0); bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32; - bool Signed = Op.getOpcode() == ISD::SINT_TO_FP; + bool Signed = Op.getOpcode() == ISD::SINT_TO_FP || + Op.getOpcode() == ISD::STRICT_SINT_TO_FP; unsigned MovOpc = (WordInt && !Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA; SDValue Mov = DAG.getNode(MovOpc, dl, MVT::f64, Src); return convertIntToFP(Op, Mov, DAG, Subtarget); @@ -8570,8 +8622,10 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { SDLoc dl(Op); - SDValue Src = Op.getOperand(0); - bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP; + bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP || + Op.getOpcode() == ISD::STRICT_SINT_TO_FP; + bool IsStrict = Op->isStrictFPOpcode(); + SDValue Src = Op.getOperand(IsStrict ? 1 : 0); EVT InVT = Src.getValueType(); EVT OutVT = Op.getValueType(); @@ -8738,9 +8792,14 @@ SDValue FP = convertIntToFP(Op, Bits, DAG, Subtarget); - if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) - FP = DAG.getNode(ISD::FP_ROUND, dl, - MVT::f32, FP, DAG.getIntPtrConstant(0, dl)); + if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) { + if (IsStrict) + FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, {MVT::f32, MVT::Other}, + {Op.getOperand(0), FP, DAG.getIntPtrConstant(0, dl)}); + else + FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, + DAG.getIntPtrConstant(0, dl)); + } return FP; } @@ -8807,9 +8866,14 @@ // FCFID it and return it. SDValue FP = convertIntToFP(Op, Ld, DAG, Subtarget); - if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) - FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, - DAG.getIntPtrConstant(0, dl)); + if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) { + if (IsStrict) + FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, {MVT::f32, MVT::Other}, + {Op.getOperand(0), FP, DAG.getIntPtrConstant(0, dl)}); + else + FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, + DAG.getIntPtrConstant(0, dl)); + } return FP; } @@ -11154,6 +11218,8 @@ case ISD::STRICT_FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::FP_TO_SINT: return LowerFP_TO_INT(Op, DAG, SDLoc(Op)); + case ISD::STRICT_UINT_TO_FP: + case ISD::STRICT_SINT_TO_FP: case ISD::UINT_TO_FP: case ISD::SINT_TO_FP: return LowerINT_TO_FP(Op, DAG); case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1572,6 +1572,15 @@ def : Pat<(unaligned4store i64:$rS, xoaddr:$dst), (STDX $rS, xoaddr:$dst)>; +def : Pat<(f64 (PPCstrict_fcfid f64:$A)), + (f64 (FCFID f64:$A))>; +def : Pat<(f64 (PPCstrict_fcfidu f64:$A)), + (f64 (FCFIDU f64:$A))>; +def : Pat<(f32 (PPCstrict_fcfids f64:$A)), + (f32 (FCFIDS f64:$A))>; +def : Pat<(f32 (PPCstrict_fcfidus f64:$A)), + (f32 (FCFIDUS f64:$A))>; + // 64-bits atomic loads and stores def : Pat<(atomic_load_64 iaddrX4:$src), (LD memrix:$src)>; def : Pat<(atomic_load_64 xaddrX4:$src), (LDX memrr:$src)>; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -134,6 +134,15 @@ def PPCfctiduz: SDNode<"PPCISD::FCTIDUZ",SDTFPUnaryOp, []>; def PPCfctiwuz: SDNode<"PPCISD::FCTIWUZ",SDTFPUnaryOp, []>; +def PPCstrict_fcfid : SDNode<"PPCISD::STRICT_FCFID", + SDTFPUnaryOp, [SDNPHasChain]>; +def PPCstrict_fcfidu : SDNode<"PPCISD::STRICT_FCFIDU", + SDTFPUnaryOp, [SDNPHasChain]>; +def PPCstrict_fcfids : SDNode<"PPCISD::STRICT_FCFIDS", + SDTFPRoundOp, [SDNPHasChain]>; +def PPCstrict_fcfidus : SDNode<"PPCISD::STRICT_FCFIDUS", + SDTFPRoundOp, [SDNPHasChain]>; + def PPCcv_fp_to_uint_in_vsr: SDNode<"PPCISD::FP_TO_UINT_IN_VSR", SDT_PPCcv_fp_to_int, []>; def PPCcv_fp_to_sint_in_vsr: diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -2430,6 +2430,15 @@ (and v4i32:$B, v4i32:$C))), (v4i32 (XXSEL $A, $B, $C))>; +def : Pat<(f64 (PPCstrict_fcfid f64:$A)), + (f64 (XSCVSXDDP f64:$A))>; +def : Pat<(f64 (PPCstrict_fcfidu f64:$A)), + (f64 (XSCVUXDDP f64:$A))>; +def : Pat<(f32 (PPCstrict_fcfids f64:$A)), + (f32 (XSCVSXDSP f64:$A))>; +def : Pat<(f32 (PPCstrict_fcfidus f64:$A)), + (f32 (XSCVUXDSP f64:$A))>; + // Additional fnmsub pattern for PPC specific ISD opcode def : Pat<(PPCfnmsub f64:$A, f64:$B, f64:$C), (XSNMSUBADP $C, $A, $B)>; @@ -3577,25 +3586,25 @@ def : Pat<(PPCfnmsub f128:$A, f128:$B, (fneg f128:$C)), (XSNMADDQP $C, $A, $B)>; -def : Pat<(f128 (sint_to_fp i64:$src)), +def : Pat<(f128 (any_sint_to_fp i64:$src)), (f128 (XSCVSDQP (COPY_TO_REGCLASS $src, VFRC)))>; -def : Pat<(f128 (sint_to_fp (i64 (PPCmfvsr f64:$src)))), +def : Pat<(f128 (any_sint_to_fp (i64 (PPCmfvsr f64:$src)))), (f128 (XSCVSDQP $src))>; -def : Pat<(f128 (sint_to_fp (i32 (PPCmfvsr f64:$src)))), +def : Pat<(f128 (any_sint_to_fp (i32 (PPCmfvsr f64:$src)))), (f128 (XSCVSDQP (VEXTSW2Ds $src)))>; -def : Pat<(f128 (uint_to_fp i64:$src)), +def : Pat<(f128 (any_uint_to_fp i64:$src)), (f128 (XSCVUDQP (COPY_TO_REGCLASS $src, VFRC)))>; -def : Pat<(f128 (uint_to_fp (i64 (PPCmfvsr f64:$src)))), +def : Pat<(f128 (any_uint_to_fp (i64 (PPCmfvsr f64:$src)))), (f128 (XSCVUDQP $src))>; // Convert (Un)Signed Word -> QP. -def : Pat<(f128 (sint_to_fp i32:$src)), +def : Pat<(f128 (any_sint_to_fp i32:$src)), (f128 (XSCVSDQP (MTVSRWA $src)))>; -def : Pat<(f128 (sint_to_fp (i32 (load xoaddr:$src)))), +def : Pat<(f128 (any_sint_to_fp (i32 (load xoaddr:$src)))), (f128 (XSCVSDQP (LIWAX xoaddr:$src)))>; -def : Pat<(f128 (uint_to_fp i32:$src)), +def : Pat<(f128 (any_uint_to_fp i32:$src)), (f128 (XSCVUDQP (MTVSRWZ $src)))>; -def : Pat<(f128 (uint_to_fp (i32 (load xoaddr:$src)))), +def : Pat<(f128 (any_uint_to_fp (i32 (load xoaddr:$src)))), (f128 (XSCVUDQP (LIWZX xoaddr:$src)))>; // Pattern for matching Vector HP -> Vector SP intrinsic. Defined as a diff --git a/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll b/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll --- a/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll +++ b/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll @@ -24,6 +24,16 @@ declare i128 @llvm.experimental.constrained.fptosi.i128.f128(fp128, metadata) declare i128 @llvm.experimental.constrained.fptoui.i128.f128(fp128, metadata) +declare fp128 @llvm.experimental.constrained.sitofp.f128.i32(i32, metadata, metadata) +declare fp128 @llvm.experimental.constrained.sitofp.f128.i64(i64, metadata, metadata) +declare fp128 @llvm.experimental.constrained.uitofp.f128.i32(i32, metadata, metadata) +declare fp128 @llvm.experimental.constrained.uitofp.f128.i64(i64, metadata, metadata) + +declare ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i32(i32, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i64(i64, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.uitofp.ppcf128.i32(i32, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.uitofp.ppcf128.i64(i64, metadata, metadata) + define i128 @q_to_i128(fp128 %m) #0 { ; P8-LABEL: q_to_i128: ; P8: # %bb.0: # %entry @@ -563,4 +573,160 @@ ret i32 %conv } +define fp128 @i32_to_q(i32 signext %m) #0 { +; P8-LABEL: i32_to_q: +; P8: # %bb.0: # %entry +; P8-NEXT: mflr r0 +; P8-NEXT: std r0, 16(r1) +; P8-NEXT: stdu r1, -112(r1) +; P8-NEXT: .cfi_def_cfa_offset 112 +; P8-NEXT: .cfi_offset lr, 16 +; P8-NEXT: bl __floatsikf +; P8-NEXT: nop +; P8-NEXT: addi r1, r1, 112 +; P8-NEXT: ld r0, 16(r1) +; P8-NEXT: mtlr r0 +; P8-NEXT: blr +; +; P9-LABEL: i32_to_q: +; P9: # %bb.0: # %entry +; P9-NEXT: mtvsrwa v2, r3 +; P9-NEXT: xscvsdqp v2, v2 +; P9-NEXT: blr +; +; NOVSX-LABEL: i32_to_q: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: mflr r0 +; NOVSX-NEXT: std r0, 16(r1) +; NOVSX-NEXT: stdu r1, -32(r1) +; NOVSX-NEXT: .cfi_def_cfa_offset 32 +; NOVSX-NEXT: .cfi_offset lr, 16 +; NOVSX-NEXT: bl __floatsikf +; NOVSX-NEXT: nop +; NOVSX-NEXT: addi r1, r1, 32 +; NOVSX-NEXT: ld r0, 16(r1) +; NOVSX-NEXT: mtlr r0 +; NOVSX-NEXT: blr +entry: + %conv = tail call fp128 @llvm.experimental.constrained.sitofp.f128.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 + ret fp128 %conv +} + +define fp128 @i64_to_q(i64 %m) #0 { +; P8-LABEL: i64_to_q: +; P8: # %bb.0: # %entry +; P8-NEXT: mflr r0 +; P8-NEXT: std r0, 16(r1) +; P8-NEXT: stdu r1, -112(r1) +; P8-NEXT: .cfi_def_cfa_offset 112 +; P8-NEXT: .cfi_offset lr, 16 +; P8-NEXT: bl __floatdikf +; P8-NEXT: nop +; P8-NEXT: addi r1, r1, 112 +; P8-NEXT: ld r0, 16(r1) +; P8-NEXT: mtlr r0 +; P8-NEXT: blr +; +; P9-LABEL: i64_to_q: +; P9: # %bb.0: # %entry +; P9-NEXT: mtvsrd v2, r3 +; P9-NEXT: xscvsdqp v2, v2 +; P9-NEXT: blr +; +; NOVSX-LABEL: i64_to_q: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: mflr r0 +; NOVSX-NEXT: std r0, 16(r1) +; NOVSX-NEXT: stdu r1, -32(r1) +; NOVSX-NEXT: .cfi_def_cfa_offset 32 +; NOVSX-NEXT: .cfi_offset lr, 16 +; NOVSX-NEXT: bl __floatdikf +; NOVSX-NEXT: nop +; NOVSX-NEXT: addi r1, r1, 32 +; NOVSX-NEXT: ld r0, 16(r1) +; NOVSX-NEXT: mtlr r0 +; NOVSX-NEXT: blr +entry: + %conv = tail call fp128 @llvm.experimental.constrained.sitofp.f128.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 + ret fp128 %conv +} + +define fp128 @u32_to_q(i32 zeroext %m) #0 { +; P8-LABEL: u32_to_q: +; P8: # %bb.0: # %entry +; P8-NEXT: mflr r0 +; P8-NEXT: std r0, 16(r1) +; P8-NEXT: stdu r1, -112(r1) +; P8-NEXT: .cfi_def_cfa_offset 112 +; P8-NEXT: .cfi_offset lr, 16 +; P8-NEXT: bl __floatunsikf +; P8-NEXT: nop +; P8-NEXT: addi r1, r1, 112 +; P8-NEXT: ld r0, 16(r1) +; P8-NEXT: mtlr r0 +; P8-NEXT: blr +; +; P9-LABEL: u32_to_q: +; P9: # %bb.0: # %entry +; P9-NEXT: mtvsrwz v2, r3 +; P9-NEXT: xscvudqp v2, v2 +; P9-NEXT: blr +; +; NOVSX-LABEL: u32_to_q: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: mflr r0 +; NOVSX-NEXT: std r0, 16(r1) +; NOVSX-NEXT: stdu r1, -32(r1) +; NOVSX-NEXT: .cfi_def_cfa_offset 32 +; NOVSX-NEXT: .cfi_offset lr, 16 +; NOVSX-NEXT: bl __floatunsikf +; NOVSX-NEXT: nop +; NOVSX-NEXT: addi r1, r1, 32 +; NOVSX-NEXT: ld r0, 16(r1) +; NOVSX-NEXT: mtlr r0 +; NOVSX-NEXT: blr +entry: + %conv = tail call fp128 @llvm.experimental.constrained.uitofp.f128.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 + ret fp128 %conv +} + +define fp128 @u64_to_q(i64 %m) #0 { +; P8-LABEL: u64_to_q: +; P8: # %bb.0: # %entry +; P8-NEXT: mflr r0 +; P8-NEXT: std r0, 16(r1) +; P8-NEXT: stdu r1, -112(r1) +; P8-NEXT: .cfi_def_cfa_offset 112 +; P8-NEXT: .cfi_offset lr, 16 +; P8-NEXT: bl __floatundikf +; P8-NEXT: nop +; P8-NEXT: addi r1, r1, 112 +; P8-NEXT: ld r0, 16(r1) +; P8-NEXT: mtlr r0 +; P8-NEXT: blr +; +; P9-LABEL: u64_to_q: +; P9: # %bb.0: # %entry +; P9-NEXT: mtvsrd v2, r3 +; P9-NEXT: xscvudqp v2, v2 +; P9-NEXT: blr +; +; NOVSX-LABEL: u64_to_q: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: mflr r0 +; NOVSX-NEXT: std r0, 16(r1) +; NOVSX-NEXT: stdu r1, -32(r1) +; NOVSX-NEXT: .cfi_def_cfa_offset 32 +; NOVSX-NEXT: .cfi_offset lr, 16 +; NOVSX-NEXT: bl __floatundikf +; NOVSX-NEXT: nop +; NOVSX-NEXT: addi r1, r1, 32 +; NOVSX-NEXT: ld r0, 16(r1) +; NOVSX-NEXT: mtlr r0 +; NOVSX-NEXT: blr +entry: + %conv = tail call fp128 @llvm.experimental.constrained.uitofp.f128.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 + ret fp128 %conv +} + attributes #0 = { strictfp } diff --git a/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll --- a/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll +++ b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll @@ -271,6 +271,20 @@ ; SPE-NEXT: # kill: def $r4 killed $r4 killed $s4 ; SPE-NEXT: # kill: def $r3 killed $r3 killed $s3 ; SPE-NEXT: blr +; +; CHECK-LABEL: i32_to_d: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprwa f0, r3 +; CHECK-NEXT: xscvsxddp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: i32_to_d: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: addi r4, r1, -4 +; NOVSX-NEXT: stw r3, -4(r1) +; NOVSX-NEXT: lfiwax f0, 0, r4 +; NOVSX-NEXT: fcfid f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret double %conv @@ -293,6 +307,19 @@ ; SPE-NEXT: addi r1, r1, 16 ; SPE-NEXT: mtlr r0 ; SPE-NEXT: blr +; +; CHECK-LABEL: i64_to_d: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprd f0, r3 +; CHECK-NEXT: xscvsxddp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: i64_to_d: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: std r3, -8(r1) +; NOVSX-NEXT: lfd f0, -8(r1) +; NOVSX-NEXT: fcfid f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call double @llvm.experimental.constrained.sitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret double %conv @@ -306,6 +333,20 @@ ; SPE-NEXT: # kill: def $r4 killed $r4 killed $s4 ; SPE-NEXT: # kill: def $r3 killed $r3 killed $s3 ; SPE-NEXT: blr +; +; CHECK-LABEL: u32_to_d: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprwz f0, r3 +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: u32_to_d: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: addi r4, r1, -4 +; NOVSX-NEXT: stw r3, -4(r1) +; NOVSX-NEXT: lfiwzx f0, 0, r4 +; NOVSX-NEXT: fcfidu f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret double %conv @@ -328,6 +369,19 @@ ; SPE-NEXT: addi r1, r1, 16 ; SPE-NEXT: mtlr r0 ; SPE-NEXT: blr +; +; CHECK-LABEL: u64_to_d: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprd f0, r3 +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: u64_to_d: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: std r3, -8(r1) +; NOVSX-NEXT: lfd f0, -8(r1) +; NOVSX-NEXT: fcfidu f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call double @llvm.experimental.constrained.uitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret double %conv @@ -338,6 +392,20 @@ ; SPE: # %bb.0: # %entry ; SPE-NEXT: efscfsi r3, r3 ; SPE-NEXT: blr +; +; CHECK-LABEL: i32_to_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprwa f0, r3 +; CHECK-NEXT: xscvsxdsp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: i32_to_f: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: addi r4, r1, -4 +; NOVSX-NEXT: stw r3, -4(r1) +; NOVSX-NEXT: lfiwax f0, 0, r4 +; NOVSX-NEXT: fcfids f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %conv @@ -356,6 +424,19 @@ ; SPE-NEXT: addi r1, r1, 16 ; SPE-NEXT: mtlr r0 ; SPE-NEXT: blr +; +; CHECK-LABEL: i64_to_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprd f0, r3 +; CHECK-NEXT: xscvsxdsp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: i64_to_f: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: std r3, -8(r1) +; NOVSX-NEXT: lfd f0, -8(r1) +; NOVSX-NEXT: fcfids f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call float @llvm.experimental.constrained.sitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %conv @@ -366,6 +447,20 @@ ; SPE: # %bb.0: # %entry ; SPE-NEXT: efscfui r3, r3 ; SPE-NEXT: blr +; +; CHECK-LABEL: u32_to_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprwz f0, r3 +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: u32_to_f: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: addi r4, r1, -4 +; NOVSX-NEXT: stw r3, -4(r1) +; NOVSX-NEXT: lfiwzx f0, 0, r4 +; NOVSX-NEXT: fcfidus f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %conv @@ -384,6 +479,19 @@ ; SPE-NEXT: addi r1, r1, 16 ; SPE-NEXT: mtlr r0 ; SPE-NEXT: blr +; +; CHECK-LABEL: u64_to_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtfprd f0, r3 +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr +; +; NOVSX-LABEL: u64_to_f: +; NOVSX: # %bb.0: # %entry +; NOVSX-NEXT: std r3, -8(r1) +; NOVSX-NEXT: lfd f0, -8(r1) +; NOVSX-NEXT: fcfidus f1, f0 +; NOVSX-NEXT: blr entry: %conv = tail call float @llvm.experimental.constrained.uitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %conv