Fixed code generation for v8i16 and v16i8 splats on X86.
authorMon P Wang <wangmp@apple.com>
Tue, 23 Dec 2008 04:03:27 +0000 (04:03 +0000)
committerMon P Wang <wangmp@apple.com>
Tue, 23 Dec 2008 04:03:27 +0000 (04:03 +0000)
Fixed lowering of v8i16 shuffles for v8i16 when we fall back to extract/insert.

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

lib/Target/X86/X86ISelLowering.cpp

index 6ad9bd21d3376a92c7afad11d66bb300bed1f840..96ad2eb97c1a15f25dab8ea572a50525ffcabd0f 100644 (file)
@@ -2554,6 +2554,23 @@ static bool isSplatMask(SDNode *N) {
   return cast<ConstantSDNode>(ElementBase)->getZExtValue() < NumElems;
 }
 
+/// getSplatMaskEltNo - Given a splat mask, return the index to the element
+/// we want to splat.
+static SDValue getSplatMaskEltNo(SDNode *N) {
+  assert(isSplatMask(N) && "Not a splat mask");
+  unsigned NumElems = N->getNumOperands();
+  SDValue ElementBase;
+  unsigned i = 0;
+  for (; i != NumElems; ++i) {
+    SDValue Elt = N->getOperand(i);
+    if (isa<ConstantSDNode>(Elt))
+      return Elt;
+  }
+  assert(0 && " No splat value found!");
+  return SDValue();
+}
+
+
 /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies
 /// a splat of a single element and it's a 2 or 4 element mask.
 bool X86::isSplatMask(SDNode *N) {
@@ -3000,15 +3017,26 @@ static SDValue PromoteSplat(SDValue Op, SelectionDAG &DAG, bool HasSSE2) {
     return Op;
   SDValue V1 = Op.getOperand(0);
   SDValue Mask = Op.getOperand(2);
-  unsigned NumElems = Mask.getNumOperands();
+  unsigned MaskNumElems = Mask.getNumOperands();
+  unsigned NumElems = MaskNumElems;
   // Special handling of v4f32 -> v4i32.
   if (VT != MVT::v4f32) {
-    Mask = getUnpacklMask(NumElems, DAG);
+    // Find which element we want to splat.
+    SDNode* EltNoNode = getSplatMaskEltNo(Mask.getNode()).getNode();
+    unsigned EltNo = cast<ConstantSDNode>(EltNoNode)->getZExtValue();
+    // unpack elements to the correct location
     while (NumElems > 4) {
+      if (EltNo < NumElems/2) {
+        Mask = getUnpacklMask(MaskNumElems, DAG);
+      } else {
+        Mask = getUnpackhMask(MaskNumElems, DAG);
+        EltNo -= NumElems/2;
+      }
       V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1, Mask);
       NumElems >>= 1;
     }
-    Mask = getZeroVector(MVT::v4i32, true, DAG);
+    SDValue Cst = DAG.getConstant(EltNo, MVT::i32);
+    Mask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Cst, Cst, Cst, Cst);
   }
 
   V1 = DAG.getNode(ISD::BIT_CONVERT, PVT, V1);
@@ -3661,8 +3689,10 @@ SDValue LowerVECTOR_SHUFFLEv8i16(SDValue V1, SDValue V2,
       ++V2InOrder;
     } else if (EltIdx < 8) {
       V1Elts.push_back(Elt);
+      V2Elts.push_back(DAG.getConstant(i+8, MaskEVT));
       ++V1FromV1;
     } else {
+      V1Elts.push_back(Elt);
       V2Elts.push_back(DAG.getConstant(EltIdx-8, MaskEVT));
       ++V2FromV2;
     }