- Implement X86ISelLowering::isShuffleMaskLegal(). We currently only support
authorEvan Cheng <evan.cheng@apple.com>
Wed, 22 Mar 2006 18:59:22 +0000 (18:59 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 22 Mar 2006 18:59:22 +0000 (18:59 +0000)
  splat and PSHUFD cases.
- Clean up shuffle / splat matching code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26954 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
lib/Target/X86/X86InstrSSE.td

index fafaf00ed1c68c19ef104a2d302dd0d94879849c..d26d7879a4547a91cac394b3a4b8cf52bdfc1601 100644 (file)
@@ -1368,6 +1368,26 @@ static bool DarwinGVRequiresExtraLoad(GlobalValue *GV) {
           (GV->isExternal() && !GV->hasNotBeenReadFromBytecode()));
 }
 
+/// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to PSHUFD.
+bool X86::isPSHUFDMask(SDNode *N) {
+  assert(N->getOpcode() == ISD::BUILD_VECTOR);
+
+  if (N->getNumOperands() != 4)
+    return false;
+
+  // Check if the value doesn't reference the second vector.
+  SDOperand Elt = N->getOperand(0);
+  assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!");
+  for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) {
+    assert(isa<ConstantSDNode>(N->getOperand(i)) &&
+           "Invalid VECTOR_SHUFFLE mask!");
+    if (cast<ConstantSDNode>(N->getOperand(i))->getValue() >= 4) return false;
+  }
+
+  return true;
+}
+
 /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies
 /// a splat of a single element.
 bool X86::isSplatMask(SDNode *N) {
@@ -2211,17 +2231,26 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
     SDOperand PermMask = Op.getOperand(2);
     MVT::ValueType VT = Op.getValueType();
 
-    if (V2.getOpcode() == ISD::UNDEF) {
-      // Handle splat cases.
-      if (X86::isSplatMask(PermMask.Val)) {
-        if (VT == MVT::v2f64 || VT == MVT::v2i64)
-          // Use unpcklpd
-          return DAG.getNode(X86ISD::UNPCKLP, VT, V1, V1);
+    // Handle splat cases.
+    if (X86::isSplatMask(PermMask.Val)) {
+      if (V2.getOpcode() == ISD::UNDEF)
         // Leave the VECTOR_SHUFFLE alone. It matches SHUFP*.
         return SDOperand();
-      } else if (VT == MVT::v4f32)
+      else
+        // Make it match SHUFP* or UNPCKLPD. Second vector is undef since it's
+        // not needed.
+        return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1,
+                           DAG.getNode(ISD::UNDEF, V1.getValueType()),
+                           PermMask);
+    } else if (X86::isPSHUFDMask(PermMask.Val)) {
+      if (V2.getOpcode() == ISD::UNDEF)
         // Leave the VECTOR_SHUFFLE alone. It matches PSHUFD.
         return SDOperand();
+      else
+        // Make it match PSHUFD. Second vector is undef since it's not needed.
+        return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1,
+                           DAG.getNode(ISD::UNDEF, V1.getValueType()),
+                           PermMask);
     }
 
     // TODO.
@@ -2262,7 +2291,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::GlobalBaseReg:      return "X86ISD::GlobalBaseReg";
   case X86ISD::Wrapper:            return "X86ISD::Wrapper";
   case X86ISD::SCALAR_TO_VECTOR:   return "X86ISD::SCALAR_TO_VECTOR";
-  case X86ISD::UNPCKLP:            return "X86ISD::UNPCKLP";
   }
 }
 
@@ -2341,3 +2369,11 @@ bool X86TargetLowering::isLegalAddressImmediate(GlobalValue *GV) const {
   } else
     return true;
 }
+
+/// isShuffleMaskLegal - Targets can use this to indicate that they only
+/// support *some* VECTOR_SHUFFLE operations, those with specific masks.
+/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
+/// are assumed to be legal.
+bool X86TargetLowering::isShuffleMaskLegal(SDOperand Mask) const {
+  return (X86::isSplatMask(Mask.Val) || X86::isPSHUFDMask(Mask.Val));
+}
index b89445796a807089bfdbbd7ff5b66ecad5d0534a..e9ff015b5af5cbd4b8c05567ca34db5e1f1091b8 100644 (file)
@@ -179,6 +179,10 @@ namespace llvm {
 
  /// Define some predicates that are used for node matching.
  namespace X86 {
+   /// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand
+   /// specifies a shuffle of elements that is suitable for input to PSHUFD.
+   bool isPSHUFDMask(SDNode *N);
+
    /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand
    /// specifies a splat of a single element.
    bool isSplatMask(SDNode *N);
@@ -259,6 +263,11 @@ namespace llvm {
     virtual bool isLegalAddressImmediate(int64_t V) const;
     virtual bool isLegalAddressImmediate(GlobalValue *GV) const;
 
+    /// isShuffleMaskLegal - Targets can use this to indicate that they only
+    /// support *some* VECTOR_SHUFFLE operations, those with specific masks.
+    /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
+    /// are assumed to be legal.
+    virtual bool isShuffleMaskLegal(SDOperand Mask) const;
   private:
     // C Calling Convention implementation.
     std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);
index aa82c2977940ba502253e04b545f347f6fadfb70..fe8bc946132e4a8c2cb9eb0b3b8b8b8ce8f09d98 100644 (file)
@@ -55,7 +55,15 @@ def SHUFP_splat_mask : PatLeaf<(build_vector), [{
   return X86::isSplatMask(N);
 }], SHUFFLE_get_shuf_imm>;
 
-def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{}], SHUFFLE_get_pshufd_imm>;
+def UNPCKLP_splat_mask : PatLeaf<(build_vector), [{
+  return X86::isSplatMask(N);
+}]>;
+
+// Only use PSHUF if it is not a splat.
+def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{
+  return !X86::isSplatMask(N) && X86::isPSHUFDMask(N);
+}], SHUFFLE_get_pshufd_imm>;
+
 
 //===----------------------------------------------------------------------===//
 // SSE scalar FP Instructions
@@ -691,9 +699,7 @@ def PSHUFWrm : PSIi8<0x70, MRMSrcMem,
                      "pshufw {$src2, $src1, $dst|$dst, $src1, $src2}", []>;
 def PSHUFDrr : PDIi8<0x70, MRMDestReg,
                      (ops VR128:$dst, VR128:$src1, i8imm:$src2),
-                     "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}",
-                 [(set VR128:$dst, (vector_shuffle (v4f32 VR128:$src1), (undef),
-                                    PSHUFD_shuffle_mask:$src2))]>;
+                     "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}", []>;
 def PSHUFDrm : PDIi8<0x70, MRMSrcMem,
                      (ops VR128:$dst, i128mem:$src1, i8imm:$src2),
                      "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}", []>;
@@ -809,12 +815,13 @@ def : Pat<(vector_shuffle (v4i32 VR128:$src), (undef), SHUFP_splat_mask:$sm),
           (v4i32 (SHUFPSrr VR128:$src, VR128:$src, SHUFP_splat_mask:$sm))>;
 
 // Splat v2f64 / v2i64
-def : Pat<(X86unpcklp (v2f64 VR128:$src1), VR128:$src2),
-          (v2f64 (UNPCKLPDrr VR128:$src1, VR128:$src2))>;
-def : Pat<(X86unpcklp (v2i64 VR128:$src1), VR128:$src2),
-          (v2i64 (UNPCKLPDrr VR128:$src1, VR128:$src2))>;
-
-// Shuffle v4i32, undef
-def : Pat<(vector_shuffle (v4i32 VR128:$src1), (undef),
-           PSHUFD_shuffle_mask:$src2),
-          (v4i32 (PSHUFDrr VR128:$src1, PSHUFD_shuffle_mask:$src2))>;
+def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), UNPCKLP_splat_mask:$sm),
+          (v2f64 (UNPCKLPDrr VR128:$src, VR128:$src))>;
+def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), UNPCKLP_splat_mask:$sm),
+          (v2i64 (UNPCKLPDrr VR128:$src, VR128:$src))>;
+
+// Shuffle v4f32 / v4i32, undef. These should only match if splat cases do not.
+def : Pat<(vector_shuffle (v4f32 VR128:$src), (undef), PSHUFD_shuffle_mask:$sm),
+          (v4f32 (PSHUFDrr VR128:$src, PSHUFD_shuffle_mask:$sm))>;
+def : Pat<(vector_shuffle (v4i32 VR128:$src), (undef), PSHUFD_shuffle_mask:$sm),
+          (v4i32 (PSHUFDrr VR128:$src, PSHUFD_shuffle_mask:$sm))>;