diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index c954f8ced8d..53c3cee5628 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -293,10 +293,50 @@ bool PPC::isVPKUWUMShuffleMask(SDNode *N) { return true; } +/// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for +/// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). +bool PPC::isVMRGLShuffleMask(SDNode *N, unsigned UnitSize) { + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); + assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && + "Unsupported merge size!"); + + for (unsigned i = 0; i != 8/UnitSize; ++i) // Step over units + for (unsigned j = 0; j != UnitSize; ++j) { // Step over bytes within unit + if (!isConstantOrUndef(N->getOperand(i*UnitSize*2+j), + 8+j+i*UnitSize) || + !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), + 24+j+i*UnitSize)) + return false; + } + return true; +} + +/// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for +/// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). +bool PPC::isVMRGHShuffleMask(SDNode *N, unsigned UnitSize) { + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); + assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && + "Unsupported merge size!"); + + for (unsigned i = 0; i != 8/UnitSize; ++i) // Step over units + for (unsigned j = 0; j != UnitSize; ++j) { // Step over bytes within unit + if (!isConstantOrUndef(N->getOperand(i*UnitSize*2+j), + 0+j+i*UnitSize) || + !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), + 16+j+i*UnitSize)) + return false; + } + return true; +} + + /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. int PPC::isVSLDOIShuffleMask(SDNode *N) { - assert(N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); // Find the first non-undef value in the shuffle mask. unsigned i; for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i) @@ -833,13 +873,19 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { if (V2.getOpcode() == ISD::UNDEF && (PPC::isSplatShuffleMask(PermMask.Val, 1) || PPC::isSplatShuffleMask(PermMask.Val, 2) || - PPC::isSplatShuffleMask(PermMask.Val, 4))) + PPC::isSplatShuffleMask(PermMask.Val, 4) || + PPC::isVSLDOIRotateShuffleMask(PermMask.Val) != -1)) return Op; if (PPC::isVPKUWUMShuffleMask(PermMask.Val) || PPC::isVPKUHUMShuffleMask(PermMask.Val) || PPC::isVSLDOIShuffleMask(PermMask.Val) != -1 || - PPC::isVSLDOIRotateShuffleMask(PermMask.Val) != -1) + PPC::isVMRGLShuffleMask(PermMask.Val, 1) || + PPC::isVMRGLShuffleMask(PermMask.Val, 2) || + PPC::isVMRGLShuffleMask(PermMask.Val, 4) || + PPC::isVMRGHShuffleMask(PermMask.Val, 1) || + PPC::isVMRGHShuffleMask(PermMask.Val, 2) || + PPC::isVMRGHShuffleMask(PermMask.Val, 4)) return Op; // TODO: Handle more cases, and also handle cases that are cheaper to do as diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 77d85c2559f..c2666ed7af9 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -109,6 +109,14 @@ namespace llvm { /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. bool isVPKUWUMShuffleMask(SDNode *N); + + /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for + /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). + bool isVMRGLShuffleMask(SDNode *N, unsigned UnitSize); + + /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for + /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). + bool isVMRGHShuffleMask(SDNode *N, unsigned UnitSize); /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index 216cbbddfef..b295641e335 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -24,6 +24,26 @@ def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{ return PPC::isVPKUWUMShuffleMask(N); }]>; +def VMRGLB_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 1); +}]>; +def VMRGLH_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 2); +}]>; +def VMRGLW_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 4); +}]>; +def VMRGHB_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 1); +}]>; +def VMRGHH_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 2); +}]>; +def VMRGHW_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 4); +}]>; + + def VSLDOI_get_imm : SDNodeXForm; @@ -278,12 +298,30 @@ def VMINUB : VX1_Int< 514, "vminub", int_ppc_altivec_vminub>; def VMINUH : VX1_Int< 578, "vminuh", int_ppc_altivec_vminuh>; def VMINUW : VX1_Int< 642, "vminuw", int_ppc_altivec_vminuw>; -def VMRGHB : VX1_Int<12 , "vmrghb", int_ppc_altivec_vmrghb>; -def VMRGHH : VX1_Int<76 , "vmrghh", int_ppc_altivec_vmrghh>; -def VMRGHW : VX1_Int<140, "vmrghw", int_ppc_altivec_vmrghw>; -def VMRGLB : VX1_Int<268, "vmrglb", int_ppc_altivec_vmrglb>; -def VMRGLH : VX1_Int<332, "vmrglh", int_ppc_altivec_vmrglh>; -def VMRGLW : VX1_Int<396, "vmrglw", int_ppc_altivec_vmrglw>; +def VMRGHB : VXForm_1< 12, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrghb $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHB_shuffle_mask))]>; +def VMRGHH : VXForm_1< 76, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrghh $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHH_shuffle_mask))]>; +def VMRGHW : VXForm_1<140, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrghw $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHW_shuffle_mask))]>; +def VMRGLB : VXForm_1<268, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrglb $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLB_shuffle_mask))]>; +def VMRGLH : VXForm_1<332, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrglh $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLH_shuffle_mask))]>; +def VMRGLW : VXForm_1<396, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), + "vmrglw $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLW_shuffle_mask))]>; def VMSUMMBM : VA1a_Int<37, "vmsummbm", int_ppc_altivec_vmsummbm>; def VMSUMSHM : VA1a_Int<40, "vmsumshm", int_ppc_altivec_vmsumshm>; diff --git a/lib/Target/PowerPC/README_ALTIVEC.txt b/lib/Target/PowerPC/README_ALTIVEC.txt index 711f7c3ba71..b9456082fb4 100644 --- a/lib/Target/PowerPC/README_ALTIVEC.txt +++ b/lib/Target/PowerPC/README_ALTIVEC.txt @@ -129,6 +129,3 @@ void test(vector int *X, vector int *Y) { //===----------------------------------------------------------------------===// -Lower "merges" in the front-end to shuffles, reconstruct in the backend. - -//===----------------------------------------------------------------------===//