Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -442,6 +442,12 @@ STRICT_FCTIDUZ, STRICT_FCTIWUZ, + /// 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 Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -221,6 +221,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); @@ -228,6 +235,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); } @@ -454,6 +463,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); } @@ -585,6 +596,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); @@ -594,8 +607,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()) { @@ -612,6 +627,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); @@ -620,6 +637,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); @@ -1482,6 +1501,14 @@ return "PPCISD::STRICT_FCTIDUZ"; case PPCISD::STRICT_FCTIWUZ: return "PPCISD::STRICT_FCTIWUZ"; + 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; } @@ -7968,6 +7995,14 @@ return PPCISD::STRICT_FCTIDUZ; case PPCISD::FCTIWUZ: return PPCISD::STRICT_FCTIWUZ; + 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; } } @@ -8135,6 +8170,10 @@ ReuseLoadInfo &RLI, SelectionDAG &DAG, ISD::LoadExtType ET) const { + // Conservatively skip reusing for constrained FP nodes. + if (Op->isStrictFPOpcode()) + return false; + SDLoc dl(Op); bool ValidFPToUint = Op.getOpcode() == ISD::FP_TO_UINT && (Subtarget.hasFPCVT() || Op.getValueType() == MVT::i32); @@ -8218,7 +8257,9 @@ 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; } @@ -8226,8 +8267,9 @@ } static SDValue convertIntToFP(SDValue Op, SDValue Src, SelectionDAG &DAG, - const PPCSubtarget &Subtarget) { - bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP; + const PPCSubtarget &Subtarget, SDValue Chain) { + 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. @@ -8235,7 +8277,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}, + {Chain, Src}); + else + return DAG.getNode(ConvOpc, dl, ConvTy, Src); } /// Custom lowers integer to floating point conversions to use @@ -8249,12 +8295,13 @@ "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); + return convertIntToFP(Op, Mov, DAG, Subtarget, Op.getOperand(0)); } static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl) { @@ -8330,8 +8377,11 @@ 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); + SDValue Chain = IsStrict ? Op.getOperand(0) : DAG.getEntryNode(); EVT InVT = Src.getValueType(); EVT OutVT = Op.getValueType(); @@ -8450,16 +8500,16 @@ int FrameIdx = MFI.CreateStackObject(4, Align(4), false); SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); - SDValue Store = - DAG.getStore(DAG.getEntryNode(), dl, SINT.getOperand(0), FIdx, - MachinePointerInfo::getFixedStack( - DAG.getMachineFunction(), FrameIdx)); + SDValue Store = DAG.getStore(Chain, dl, SINT.getOperand(0), FIdx, + MachinePointerInfo::getFixedStack( + DAG.getMachineFunction(), FrameIdx)); + Chain = Store; assert(cast(Store)->getMemoryVT() == MVT::i32 && "Expected an i32 store"); RLI.Ptr = FIdx; - RLI.Chain = Store; + RLI.Chain = Chain; RLI.MPI = MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx); RLI.Alignment = Align(4); @@ -8472,14 +8522,22 @@ PPCISD::LFIWZX : PPCISD::LFIWAX, dl, DAG.getVTList(MVT::f64, MVT::Other), Ops, MVT::i32, MMO); + Chain = Bits.getValue(1); } else Bits = DAG.getNode(ISD::BITCAST, dl, MVT::f64, SINT); - SDValue FP = convertIntToFP(Op, Bits, DAG, Subtarget); + SDValue FP = convertIntToFP(Op, Bits, DAG, Subtarget, Chain); + if (IsStrict) + Chain = FP.getValue(1); - 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}, + {Chain, FP, DAG.getIntPtrConstant(0, dl)}); + else + FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, + DAG.getIntPtrConstant(0, dl)); + } return FP; } @@ -8501,15 +8559,16 @@ int FrameIdx = MFI.CreateStackObject(4, Align(4), false); SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Src, FIdx, + SDValue Store = DAG.getStore(Chain, dl, Src, FIdx, MachinePointerInfo::getFixedStack( DAG.getMachineFunction(), FrameIdx)); + Chain = Store; assert(cast(Store)->getMemoryVT() == MVT::i32 && "Expected an i32 store"); RLI.Ptr = FIdx; - RLI.Chain = Store; + RLI.Chain = Chain; RLI.MPI = MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx); RLI.Alignment = Align(4); @@ -8522,6 +8581,7 @@ Ld = DAG.getMemIntrinsicNode(IsSigned ? PPCISD::LFIWAX : PPCISD::LFIWZX, dl, DAG.getVTList(MVT::f64, MVT::Other), Ops, MVT::i32, MMO); + Chain = Ld.getValue(1); if (ReusingLoad) spliceIntoChain(RLI.ResChain, Ld.getValue(1), DAG); } else { @@ -8535,20 +8595,29 @@ // STD the extended value into the stack slot. SDValue Store = DAG.getStore( - DAG.getEntryNode(), dl, Ext64, FIdx, + Chain, dl, Ext64, FIdx, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx)); + Chain = Store; // Load the value as a double. Ld = DAG.getLoad( - MVT::f64, dl, Store, FIdx, + MVT::f64, dl, Chain, FIdx, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx)); + Chain = Ld.getValue(1); } // 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)); + SDValue FP = convertIntToFP(Op, Ld, DAG, Subtarget, Chain); + if (IsStrict) + Chain = FP.getValue(1); + if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) { + if (IsStrict) + FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, {MVT::f32, MVT::Other}, + {Chain, FP, DAG.getIntPtrConstant(0, dl)}); + else + FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, + DAG.getIntPtrConstant(0, dl)); + } return FP; } @@ -10516,6 +10585,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); Index: llvm/lib/Target/PowerPC/PPCInstr64Bit.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1577,6 +1577,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)>; Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ 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: Index: llvm/lib/Target/PowerPC/PPCInstrVSX.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ 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)>; @@ -3571,25 +3580,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 Index: llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll =================================================================== --- llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll +++ llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll @@ -26,6 +26,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 @@ -581,6 +591,162 @@ 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 +} + define void @fptoint_nofpexcept(fp128 %m, i32* %addr1, i64* %addr2) { ; MIR-LABEL: name: fptoint_nofpexcept ; MIR: renamable $v{{[0-9]+}} = nofpexcept XSCVQPSWZ Index: llvm/test/CodeGen/PowerPC/fp-strict-conv.ll =================================================================== --- llvm/test/CodeGen/PowerPC/fp-strict-conv.ll +++ llvm/test/CodeGen/PowerPC/fp-strict-conv.ll @@ -178,4 +178,152 @@ ret i32 %conv } +define double @i32_to_d(i32 signext %m) #0 { +; 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 +} + +define double @i64_to_d(i64 %m) #0 { +; 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 +} + +define double @u32_to_d(i32 zeroext %m) #0 { +; 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 +} + +define double @u64_to_d(i64 %m) #0 { +; 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 +} + +define float @i32_to_f(i32 signext %m) #0 { +; 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 +} + +define float @i64_to_f(i64 %m) #0 { +; 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 +} + +define float @u32_to_f(i32 zeroext %m) #0 { +; 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 +} + +define float @u64_to_f(i64 %m) #0 { +; 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 +} + attributes #0 = { strictfp }