From caad163496a3ad207a75009f4ad16bae1b1527ae Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 6 Apr 2006 22:02:42 +0000 Subject: [PATCH] Add support for matching vmrg(x,x) patterns git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27463 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 72 ++++++++++++++------------ lib/Target/PowerPC/PPCISelLowering.h | 4 +- lib/Target/PowerPC/PPCInstrAltivec.td | 46 +++++++++++++--- 3 files changed, 81 insertions(+), 41 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 53c3cee5628..a7608657ef2 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -293,9 +293,10 @@ 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) { +/// isVMerge - Common function, used to match vmrg* shuffles. +/// +static bool isVMerge(SDNode *N, unsigned UnitSize, + unsigned LHSStart, unsigned RHSStart) { assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && @@ -304,31 +305,28 @@ bool PPC::isVMRGLShuffleMask(SDNode *N, unsigned UnitSize) { 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) || + LHSStart+j+i*UnitSize) || !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), - 24+j+i*UnitSize)) + RHSStart+j+i*UnitSize)) return false; } - return true; + 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, bool isUnary) { + if (!isUnary) + return isVMerge(N, UnitSize, 8, 24); + return isVMerge(N, UnitSize, 8, 8); } /// 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; +bool PPC::isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { + if (!isUnary) + return isVMerge(N, UnitSize, 0, 16); + return isVMerge(N, UnitSize, 0, 0); } @@ -870,22 +868,30 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { // Cases that are handled by instructions that take permute immediates // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be // selected by the instruction selector. - if (V2.getOpcode() == ISD::UNDEF && - (PPC::isSplatShuffleMask(PermMask.Val, 1) || - PPC::isSplatShuffleMask(PermMask.Val, 2) || - PPC::isSplatShuffleMask(PermMask.Val, 4) || - PPC::isVSLDOIRotateShuffleMask(PermMask.Val) != -1)) - return Op; + if (V2.getOpcode() == ISD::UNDEF) { + if (PPC::isSplatShuffleMask(PermMask.Val, 1) || + PPC::isSplatShuffleMask(PermMask.Val, 2) || + PPC::isSplatShuffleMask(PermMask.Val, 4) || + PPC::isVSLDOIRotateShuffleMask(PermMask.Val) != -1 || + PPC::isVMRGLShuffleMask(PermMask.Val, 1, true) || + PPC::isVMRGLShuffleMask(PermMask.Val, 2, true) || + PPC::isVMRGLShuffleMask(PermMask.Val, 4, true) || + PPC::isVMRGHShuffleMask(PermMask.Val, 1, true) || + PPC::isVMRGHShuffleMask(PermMask.Val, 2, true) || + PPC::isVMRGHShuffleMask(PermMask.Val, 4, true)) { + return Op; + } + } if (PPC::isVPKUWUMShuffleMask(PermMask.Val) || PPC::isVPKUHUMShuffleMask(PermMask.Val) || PPC::isVSLDOIShuffleMask(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)) + PPC::isVMRGLShuffleMask(PermMask.Val, 1, false) || + PPC::isVMRGLShuffleMask(PermMask.Val, 2, false) || + PPC::isVMRGLShuffleMask(PermMask.Val, 4, false) || + PPC::isVMRGHShuffleMask(PermMask.Val, 1, false) || + PPC::isVMRGHShuffleMask(PermMask.Val, 2, false) || + PPC::isVMRGHShuffleMask(PermMask.Val, 4, false)) 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 c2666ed7af9..559256b4d11 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -112,11 +112,11 @@ namespace llvm { /// 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); + bool isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); /// 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); + bool isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); /// 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 b295641e335..2120a02582f 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -25,22 +25,41 @@ def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{ }]>; def VMRGLB_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 1); + return PPC::isVMRGLShuffleMask(N, 1, false); }]>; def VMRGLH_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 2); + return PPC::isVMRGLShuffleMask(N, 2, false); }]>; def VMRGLW_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 4); + return PPC::isVMRGLShuffleMask(N, 4, false); }]>; def VMRGHB_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 1); + return PPC::isVMRGHShuffleMask(N, 1, false); }]>; def VMRGHH_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 2); + return PPC::isVMRGHShuffleMask(N, 2, false); }]>; def VMRGHW_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 4); + return PPC::isVMRGHShuffleMask(N, 4, false); +}]>; + +def VMRGLB_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 1, true); +}]>; +def VMRGLH_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 2, true); +}]>; +def VMRGLW_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 4, true); +}]>; +def VMRGHB_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 1, true); +}]>; +def VMRGHH_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 2, true); +}]>; +def VMRGHW_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 4, true); }]>; @@ -566,6 +585,21 @@ def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>; def:Pat<(vector_shuffle (v16i8 VRRC:$vA),undef, VSLDOI_rotate_shuffle_mask:$in), (VSLDOI VRRC:$vA, VRRC:$vA, VSLDOI_rotate_shuffle_mask:$in)>; +// Match vmrg*(x,x) +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLB_unary_shuffle_mask:$in), + (VMRGLB VRRC:$vA, VRRC:$vA)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLH_unary_shuffle_mask:$in), + (VMRGLH VRRC:$vA, VRRC:$vA)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLW_unary_shuffle_mask:$in), + (VMRGLW VRRC:$vA, VRRC:$vA)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHB_unary_shuffle_mask:$in), + (VMRGHB VRRC:$vA, VRRC:$vA)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHH_unary_shuffle_mask:$in), + (VMRGHH VRRC:$vA, VRRC:$vA)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHW_unary_shuffle_mask:$in), + (VMRGHW VRRC:$vA, VRRC:$vA)>; + + // Immediate vector formation with vsplti*. def : Pat<(v16i8 vecspltisb:$invec), (v16i8 (VSPLTISB vecspltisb:$invec))>; def : Pat<(v16i8 vecspltish:$invec), (v16i8 (VSPLTISH vecspltish:$invec))>;