Support for scalar to vector with zero extension.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27091 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index e9178f2..0a9f4b4 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1398,8 +1398,8 @@
 bool X86::isSHUFPMask(SDNode *N) {
   assert(N->getOpcode() == ISD::BUILD_VECTOR);
 
-  unsigned NumOperands = N->getNumOperands();
-  if (NumOperands == 2) {
+  unsigned NumElems = N->getNumOperands();
+  if (NumElems == 2) {
     // The only case that ought be handled by SHUFPD is
     // Dest { 2, 1 } <=  shuffle( Dest { 1, 0 },  Src { 3, 2 }
     // Expect bit 0 == 1, bit1 == 2
@@ -1411,21 +1411,21 @@
             cast<ConstantSDNode>(Bit1)->getValue() == 2);
   }
 
-  if (NumOperands != 4) return false;
+  if (NumElems != 4) return false;
 
   // Each half must refer to only one of the vector.
   SDOperand Elt = N->getOperand(0);
   assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!");
-  for (unsigned i = 1; i != NumOperands / 2; ++i) {
+  for (unsigned i = 1; i != NumElems / 2; ++i) {
     assert(isa<ConstantSDNode>(N->getOperand(i)) &&
            "Invalid VECTOR_SHUFFLE mask!");
     if (cast<ConstantSDNode>(N->getOperand(i))->getValue() != 
         cast<ConstantSDNode>(Elt)->getValue())
       return false;
   }
-  Elt = N->getOperand(NumOperands / 2);
+  Elt = N->getOperand(NumElems / 2);
   assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!");
-  for (unsigned i = NumOperands / 2; i != NumOperands; ++i) {
+  for (unsigned i = NumElems / 2; i != NumElems; ++i) {
     assert(isa<ConstantSDNode>(N->getOperand(i)) &&
            "Invalid VECTOR_SHUFFLE mask!");
     if (cast<ConstantSDNode>(N->getOperand(i))->getValue() != 
@@ -1530,20 +1530,23 @@
   return Mask;
 }
 
-/// isZeroVector - Return true if all elements of BUILD_VECTOR are 0 or +0.0.
+/// isZeroVector - Return true if this build_vector is an all-zero vector.
+///
 bool X86::isZeroVector(SDNode *N) {
-  for (SDNode::op_iterator I = N->op_begin(), E = N->op_end();
-       I != E; ++I) {
-    if (ConstantFPSDNode *FPC = dyn_cast<ConstantFPSDNode>(*I)) {
-      if (!FPC->isExactlyValue(+0.0))
+  if (MVT::isInteger(N->getOperand(0).getValueType())) {
+    for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+      if (!isa<ConstantSDNode>(N->getOperand(i)) ||
+          cast<ConstantSDNode>(N->getOperand(i))->getValue() != 0)
         return false;
-    } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(*I)) {
-      if (!C->isNullValue())
+  } else {
+    assert(MVT::isFloatingPoint(N->getOperand(0).getValueType()) &&
+           "Vector of non-int, non-float values?");
+    // See if this is all zeros.
+    for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+      if (!isa<ConstantFPSDNode>(N->getOperand(i)) ||
+          !cast<ConstantFPSDNode>(N->getOperand(i))->isExactlyValue(0.0))
         return false;
-    } else
-      return false;
   }
-
   return true;
 }
 
@@ -2318,7 +2321,7 @@
   }
   case ISD::SCALAR_TO_VECTOR: {
     SDOperand AnyExt = DAG.getNode(ISD::ANY_EXTEND, MVT::i32, Op.getOperand(0));
-    return DAG.getNode(X86ISD::SCALAR_TO_VECTOR, Op.getValueType(), AnyExt);
+    return DAG.getNode(X86ISD::S2VEC, Op.getValueType(), AnyExt);
   }
   case ISD::VECTOR_SHUFFLE: {
     SDOperand V1 = Op.getOperand(0);
@@ -2338,6 +2341,9 @@
         return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1,
                            DAG.getNode(ISD::UNDEF, V1.getValueType()),
                            PermMask);
+    } else if (NumElems == 2) {
+      // All v2f64 cases are handled.
+      return SDOperand();
     } else if (X86::isPSHUFDMask(PermMask.Val)) {
       if (V2.getOpcode() == ISD::UNDEF)
         // Leave the VECTOR_SHUFFLE alone. It matches PSHUFD.
@@ -2347,9 +2353,6 @@
         return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1,
                            DAG.getNode(ISD::UNDEF, V1.getValueType()),
                            PermMask);
-    } else if (NumElems == 2) {
-      // All v2f64 cases are handled.
-      return SDOperand();
     } else if (X86::isSHUFPMask(PermMask.Val)) {
       SDOperand Elt = PermMask.getOperand(0);
       if (cast<ConstantSDNode>(Elt)->getValue() >= NumElems) {
@@ -2370,22 +2373,32 @@
     abort();
   }
   case ISD::BUILD_VECTOR: {
-    bool isZero = true;
+    SDOperand Elt0 = Op.getOperand(0);
+    bool Elt0IsZero = (isa<ConstantSDNode>(Elt0) &&
+                       cast<ConstantSDNode>(Elt0)->getValue() == 0) ||
+      (isa<ConstantFPSDNode>(Elt0) &&
+       cast<ConstantFPSDNode>(Elt0)->isExactlyValue(0.0));
+    bool RestAreZero = true;
     unsigned NumElems = Op.getNumOperands();
-    for (unsigned i = 0; i < NumElems; ++i) {
+    for (unsigned i = 1; i < NumElems; ++i) {
       SDOperand V = Op.getOperand(i);
       if (ConstantFPSDNode *FPC = dyn_cast<ConstantFPSDNode>(V)) {
         if (!FPC->isExactlyValue(+0.0))
-          isZero = false;
+          RestAreZero = false;
       } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(V)) {
         if (!C->isNullValue())
-          isZero = false;
+          RestAreZero = false;
       } else
-        isZero = false;
+        RestAreZero = false;
     }
 
-    if (isZero)
-      return Op;
+    if (RestAreZero) {
+      if (Elt0IsZero) return Op;
+
+      // Zero extend a scalar to a vector.
+      return DAG.getNode(X86ISD::ZEXT_S2VEC, Op.getValueType(), Elt0);
+    }
+
     return SDOperand();
   }
   }
@@ -2421,7 +2434,8 @@
   case X86ISD::LOAD_PACK:          return "X86ISD::LOAD_PACK";
   case X86ISD::GlobalBaseReg:      return "X86ISD::GlobalBaseReg";
   case X86ISD::Wrapper:            return "X86ISD::Wrapper";
-  case X86ISD::SCALAR_TO_VECTOR:   return "X86ISD::SCALAR_TO_VECTOR";
+  case X86ISD::S2VEC:              return "X86ISD::S2VEC";
+  case X86ISD::ZEXT_S2VEC:         return "X86ISD::ZEXT_S2VEC";
   }
 }