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
This commit is contained in:
Chris Lattner 2006-04-06 22:02:42 +00:00
parent cc8b1ac5cb
commit caad163496
3 changed files with 81 additions and 41 deletions

View File

@ -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

View File

@ -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.

View File

@ -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))>;