Compile the vpkuhum/vpkuwum intrinsics into vpkuhum/vpkuwum instead of into
vperm with a perm mask lvx'd from the constant pool.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27448 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 8cf7052..db9e390 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -267,6 +267,56 @@
   return false;
 }
 
+/// isConstantOrUndef - Op is either an undef node or a ConstantSDNode.  Return
+/// true if Op is undef or if it matches the specified value.
+static bool isConstantOrUndef(SDOperand Op, unsigned Val) {
+  return Op.getOpcode() == ISD::UNDEF || 
+         cast<ConstantSDNode>(Op)->getValue() == Val;
+}
+
+/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a
+/// VPKUHUM instruction.
+bool PPC::isVPKUHUMShuffleMask(SDNode *N) {
+  return isConstantOrUndef(N->getOperand( 0),  1) &&
+         isConstantOrUndef(N->getOperand( 1),  3) &&
+         isConstantOrUndef(N->getOperand( 2),  5) &&
+         isConstantOrUndef(N->getOperand( 3),  7) &&
+         isConstantOrUndef(N->getOperand( 4),  9) &&
+         isConstantOrUndef(N->getOperand( 5), 11) &&
+         isConstantOrUndef(N->getOperand( 6), 13) &&
+         isConstantOrUndef(N->getOperand( 7), 15) &&
+         isConstantOrUndef(N->getOperand( 8), 17) &&
+         isConstantOrUndef(N->getOperand( 9), 19) &&
+         isConstantOrUndef(N->getOperand(10), 21) &&
+         isConstantOrUndef(N->getOperand(11), 23) &&
+         isConstantOrUndef(N->getOperand(12), 25) &&
+         isConstantOrUndef(N->getOperand(13), 27) &&
+         isConstantOrUndef(N->getOperand(14), 29) &&
+         isConstantOrUndef(N->getOperand(15), 31);
+}
+
+/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a
+/// VPKUWUM instruction.
+bool PPC::isVPKUWUMShuffleMask(SDNode *N) {
+  return isConstantOrUndef(N->getOperand( 0),  2) &&
+         isConstantOrUndef(N->getOperand( 1),  3) &&
+         isConstantOrUndef(N->getOperand( 2),  6) &&
+         isConstantOrUndef(N->getOperand( 3),  7) &&
+         isConstantOrUndef(N->getOperand( 4), 10) &&
+         isConstantOrUndef(N->getOperand( 5), 11) &&
+         isConstantOrUndef(N->getOperand( 6), 14) &&
+         isConstantOrUndef(N->getOperand( 7), 15) &&
+         isConstantOrUndef(N->getOperand( 8), 18) &&
+         isConstantOrUndef(N->getOperand( 9), 19) &&
+         isConstantOrUndef(N->getOperand(10), 22) &&
+         isConstantOrUndef(N->getOperand(11), 23) &&
+         isConstantOrUndef(N->getOperand(12), 26) &&
+         isConstantOrUndef(N->getOperand(13), 27) &&
+         isConstantOrUndef(N->getOperand(14), 30) &&
+         isConstantOrUndef(N->getOperand(15), 31);
+}
+
+
 
 /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand
 /// specifies a splat of a single element that is suitable for input to
@@ -759,6 +809,10 @@
          PPC::isSplatShuffleMask(PermMask.Val, 4)))
       return Op;
     
+    if (PPC::isVPKUWUMShuffleMask(PermMask.Val) ||
+        PPC::isVPKUHUMShuffleMask(PermMask.Val))
+      return Op;
+    
     // TODO: Handle more cases, and also handle cases that are cheaper to do as
     // multiple such instructions than as a constant pool load/vperm pair.