Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -927,6 +927,9 @@ SDValue LowerINT_TO_FPDirectMove(SDValue Op, SelectionDAG &DAG, const SDLoc &dl) const; + SDValue LowerINT_TO_FPVector(SDValue Op, SelectionDAG &DAG, + const SDLoc &dl) const; + SDValue getFramePointerFrameIndex(SelectionDAG & DAG) const; SDValue getReturnAddrFrameIndex(SelectionDAG & DAG) const; Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -792,6 +792,9 @@ setOperationAction(ISD::FP_TO_SINT, MVT::v2i64, Legal); setOperationAction(ISD::FP_TO_UINT, MVT::v2i64, Legal); + setOperationAction(ISD::UINT_TO_FP, MVT::v2i16, Custom); + setOperationAction(ISD::SINT_TO_FP, MVT::v2i16, Custom); + setOperationAction(ISD::FNEG, MVT::v4f32, Legal); setOperationAction(ISD::FNEG, MVT::v2f64, Legal); setOperationAction(ISD::FABS, MVT::v4f32, Legal); @@ -7263,10 +7266,68 @@ return FP; } +static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl) { + + EVT VecVT = Vec.getValueType(); + assert(VecVT.isVector() && "Expected a vector type."); + assert(VecVT.getSizeInBits() < 128 && "Vector is already full width."); + + EVT EltVT = VecVT.getVectorElementType(); + unsigned WideNum = 128 / EltVT.getSizeInBits(); + EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT, WideNum); + + unsigned SourceNum = WideNum / VecVT.getVectorNumElements(); + SmallVector Sources(SourceNum); + Sources[0] = Vec; + SDValue UndefVec = DAG.getUNDEF(VecVT); + for (unsigned i = 1; i < SourceNum; ++i) + Sources[i] = UndefVec; + + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WideVT, Sources); +} + +SDValue PPCTargetLowering::LowerINT_TO_FPVector(SDValue Op, + SelectionDAG &DAG, + const SDLoc &dl) const { + + unsigned Opc = Op.getOpcode(); + assert((Opc == ISD::UINT_TO_FP || Opc == ISD::SINT_TO_FP) && + "Unexpected conversion type"); + assert(Op.getValueType() == MVT::v2f64 && "Supports v2f64 only."); + + // CPU's prior to P9 don't have a way to sign-extend in vectors. + bool SignedConv = Opc == ISD::SINT_TO_FP; + if (SignedConv && !Subtarget.hasP9Altivec()) + return SDValue(); + + SDValue Wide = widenVec(DAG, Op.getOperand(0), dl); + EVT WideVT = Wide.getValueType(); + unsigned WideNum = WideVT.getVectorNumElements(); + + SmallVector ShuffV; + for (unsigned i = 0; i < WideNum; ++i) + ShuffV.push_back(i + WideNum); + ShuffV[0] = 0; + ShuffV[WideNum / 2] = 1; + + SDValue ShuffleSrc2 = SignedConv ? DAG.getUNDEF(WideVT) : + DAG.getConstant(0, dl, WideVT); + SDValue Arrange = DAG.getVectorShuffle(WideVT, dl, Wide, ShuffleSrc2, ShuffV); + unsigned ExtendOp = SignedConv ? (unsigned) PPCISD::SExtVElems : + (unsigned) ISD::BITCAST; + SDValue Extend = DAG.getNode(ExtendOp, dl, MVT::v2i64, Arrange); + + return DAG.getNode(Opc, dl, Op.getValueType(), Extend); +} + SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { SDLoc dl(Op); + if (Op.getValueType() == MVT::v2f64 && + Op.getOperand(0).getValueType() == MVT::v2i16) + return LowerINT_TO_FPVector(Op, DAG, dl); + // Conversions to f128 are legal. if (EnableQuadPrecision && (Op.getValueType() == MVT::f128)) return Op; Index: llvm/test/CodeGen/PowerPC/vec-itofp.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/vec-itofp.ll @@ -0,0 +1,105 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr8 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-P8 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-P9 + +define void @test8(<8 x double>* nocapture %Sink, <8 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <8 x i16>, <8 x i16>* %SrcPtr, align 16 + %1 = uitofp <8 x i16> %0 to <8 x double> + store <8 x double> %1, <8 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @test8 +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: xvcvuxddp +; CHECK-P9: xvcvuxddp +; CHECK-P9: xvcvuxddp +; CHECK-P9: xvcvuxddp +; CHECK-P8-LABEL: @test8 +; CHECK-P8: vperm +; CHECK-P8: vperm +; CHECK-P8: vperm +; CHECK-P8: vperm +; CHECK-P8: xvcvuxddp +; CHECK-P8: xvcvuxddp +; CHECK-P8: xvcvuxddp +; CHECK-P8: xvcvuxddp +} + +define void @test4(<4 x double>* nocapture %Sink, <4 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <4 x i16>, <4 x i16>* %SrcPtr, align 16 + %1 = uitofp <4 x i16> %0 to <4 x double> + store <4 x double> %1, <4 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @test4 +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: xvcvuxddp +; CHECK-P9: xvcvuxddp +; CHECK-P8-LABEL: @test4 +; CHECK-P8: vperm +; CHECK-P8: vperm +; CHECK-P8: xvcvuxddp +; CHECK-P8: xvcvuxddp +} + +define void @test2(<2 x double>* nocapture %Sink, <2 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <2 x i16>, <2 x i16>* %SrcPtr, align 16 + %1 = uitofp <2 x i16> %0 to <2 x double> + store <2 x double> %1, <2 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @test2 +; CHECK-P9: vperm [[REG1:v[0-9]+]] +; CHECK-P9: xvcvuxddp {{vs[0-9]+}}, [[REG1]] +; CHECK-P8-LABEL: @test2 +; CHECK-P8: vperm [[REG1:v[0-9]+]] +; CHECK-P8: xvcvuxddp {{vs[0-9]+}}, [[REG1]] +} + +define void @stest8(<8 x double>* nocapture %Sink, <8 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <8 x i16>, <8 x i16>* %SrcPtr, align 16 + %1 = sitofp <8 x i16> %0 to <8 x double> + store <8 x double> %1, <8 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @stest8 +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: xvcvsxddp +; CHECK-P9: xvcvsxddp +; CHECK-P9: xvcvsxddp +; CHECK-P9: xvcvsxddp +} + +define void @stest4(<4 x double>* nocapture %Sink, <4 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <4 x i16>, <4 x i16>* %SrcPtr, align 16 + %1 = sitofp <4 x i16> %0 to <4 x double> + store <4 x double> %1, <4 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @stest4 +; CHECK-P9: vperm +; CHECK-P9: vperm +; CHECK-P9: xvcvsxddp +; CHECK-P9: xvcvsxddp +} + +define void @stest2(<2 x double>* nocapture %Sink, <2 x i16>* nocapture readonly %SrcPtr) { +entry: + %0 = load <2 x i16>, <2 x i16>* %SrcPtr, align 16 + %1 = sitofp <2 x i16> %0 to <2 x double> + store <2 x double> %1, <2 x double>* %Sink, align 16 + ret void +; CHECK-P9-LABEL: @stest2 +; CHECK-P9: vperm [[REG1:v[0-9]+]] +; CHECK-P9: xvcvsxddp {{vs[0-9]+}}, [[REG1]] +}