diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index c3f36756f6f..d216026d2e7 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -1335,6 +1335,43 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { return CurDAG->SelectNodeTo(N, PPC::XXSEL, N->getValueType(0), Ops, 3); } + break; + case ISD::VECTOR_SHUFFLE: + if (PPCSubTarget.hasVSX() && (N->getValueType(0) == MVT::v2f64 || + N->getValueType(0) == MVT::v2i64)) { + ShuffleVectorSDNode *SVN = cast(N); + + SDValue Op1 = N->getOperand(SVN->getMaskElt(0) < 2 ? 0 : 1), + Op2 = N->getOperand(SVN->getMaskElt(1) < 2 ? 0 : 1); + unsigned DM[2]; + + for (int i = 0; i < 2; ++i) + if (SVN->getMaskElt(i) <= 0 || SVN->getMaskElt(i) == 2) + DM[i] = 0; + else + DM[i] = 1; + + SDValue DMV = CurDAG->getTargetConstant(DM[0] | (DM[1] << 1), MVT::i32); + + if (Op1 == Op2 && DM[0] == 0 && DM[1] == 0 && + Op1.getOpcode() == ISD::SCALAR_TO_VECTOR && + isa(Op1.getOperand(0))) { + LoadSDNode *LD = cast(Op1.getOperand(0)); + SDValue Base, Offset; + + if (LD->isUnindexed() && + SelectAddrIdxOnly(LD->getBasePtr(), Base, Offset)) { + SDValue Chain = LD->getChain(); + SDValue Ops[] = { Base, Offset, Chain }; + return CurDAG->SelectNodeTo(N, PPC::LXVDSX, + N->getValueType(0), Ops, 3); + } + } + + SDValue Ops[] = { Op1, Op2, DMV }; + return CurDAG->SelectNodeTo(N, PPC::XXPERMDI, N->getValueType(0), Ops, 3); + } + break; case PPCISD::BDNZ: case PPCISD::BDZ: { diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 87639247e21..6f640183f93 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -570,6 +570,8 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::LOAD, MVT::v2f64, Legal); setOperationAction(ISD::STORE, MVT::v2f64, Legal); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2f64, Legal); + addRegisterClass(MVT::f64, &PPC::VSRCRegClass); addRegisterClass(MVT::v4f32, &PPC::VSRCRegClass); @@ -584,6 +586,8 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::STORE, MVT::v2i64, Promote); AddPromotedToType (ISD::STORE, MVT::v2i64, MVT::v2f64); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i64, Legal); + setOperationAction(ISD::SINT_TO_FP, MVT::v2i64, Legal); setOperationAction(ISD::UINT_TO_FP, MVT::v2i64, Legal); setOperationAction(ISD::FP_TO_SINT, MVT::v2i64, Legal); @@ -872,8 +876,8 @@ bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { /// static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned LHSStart, unsigned RHSStart) { - assert(N->getValueType(0) == MVT::v16i8 && - "PPC only supports shuffles by bytes!"); + if (N->getValueType(0) != MVT::v16i8) + return false; assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && "Unsupported merge size!"); @@ -910,8 +914,8 @@ bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { - assert(N->getValueType(0) == MVT::v16i8 && - "PPC only supports shuffles by bytes!"); + if (N->getValueType(0) != MVT::v16i8) + return false; ShuffleVectorSDNode *SVOp = cast(N); diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td index 8410912c20a..643ba1fbb02 100644 --- a/lib/Target/PowerPC/PPCInstrVSX.td +++ b/lib/Target/PowerPC/PPCInstrVSX.td @@ -53,7 +53,6 @@ let Uses = [RM] in { def LXVDSX : XForm_1<31, 332, (outs vsrc:$XT), (ins memrr:$src), "lxvdsx $XT, $src", IIC_LdStLFD, []>; - // TODO: match load + splat to lxvdsx. def LXVW4X : XForm_1<31, 780, (outs vsrc:$XT), (ins memrr:$src), diff --git a/test/CodeGen/PowerPC/vsx.ll b/test/CodeGen/PowerPC/vsx.ll index 36848427a55..2524251a20a 100644 --- a/test/CodeGen/PowerPC/vsx.ll +++ b/test/CodeGen/PowerPC/vsx.ll @@ -422,3 +422,68 @@ define <2 x i64> @test47(<2 x float> %a) { ; CHECK: blr } +define <2 x double> @test50(double* %a) { + %v = load double* %a, align 8 + %w = insertelement <2 x double> undef, double %v, i32 0 + %x = insertelement <2 x double> %w, double %v, i32 1 + ret <2 x double> %x + +; CHECK-LABEL: @test50 +; CHECK: lxvdsx 34, 0, 3 +; CHECK: blr +} + +define <2 x double> @test51(<2 x double> %a, <2 x double> %b) { + %v = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> + ret <2 x double> %v + +; CHECK-LABEL: @test51 +; CHECK: xxpermdi 34, 34, 34, 0 +; CHECK: blr +} + +define <2 x double> @test52(<2 x double> %a, <2 x double> %b) { + %v = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> + ret <2 x double> %v + +; CHECK-LABEL: @test52 +; CHECK: xxpermdi 34, 34, 35, 0 +; CHECK: blr +} + +define <2 x double> @test53(<2 x double> %a, <2 x double> %b) { + %v = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> + ret <2 x double> %v + +; CHECK-LABEL: @test53 +; CHECK: xxpermdi 34, 35, 34, 0 +; CHECK: blr +} + +define <2 x double> @test54(<2 x double> %a, <2 x double> %b) { + %v = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> + ret <2 x double> %v + +; CHECK-LABEL: @test54 +; CHECK: xxpermdi 34, 34, 35, 1 +; CHECK: blr +} + +define <2 x double> @test55(<2 x double> %a, <2 x double> %b) { + %v = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> + ret <2 x double> %v + +; CHECK-LABEL: @test55 +; CHECK: xxpermdi 34, 34, 35, 3 +; CHECK: blr +} + +define <2 x i64> @test56(<2 x i64> %a, <2 x i64> %b) { + %v = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> + ret <2 x i64> %v + +; CHECK-LABEL: @test56 +; CHECK: xxpermdi 34, 34, 35, 3 +; CHECK: blr +} +