Add support for matching vmrg(x,x) patterns
authorChris Lattner <sabre@nondot.org>
Thu, 6 Apr 2006 22:02:42 +0000 (22:02 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 6 Apr 2006 22:02:42 +0000 (22:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27463 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
lib/Target/PowerPC/PPCInstrAltivec.td

index 53c3cee5628f9e04fe92d5dedb464bc523aff44d..a7608657ef232641dab8a99681958acd4f535cff 100644 (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
index c2666ed7af92a1147976bfc4a720cb44150ccdf7..559256b4d118758caa4ce0c266b1d20f4a0685b0 100644 (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.
index b295641e335d52f68163c4207259a8bc3de3be4e..2120a02582fd0716b60a4bf4ce1c93b1d2e19e91 100644 (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))>;