[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp X86ISelLowering.h X86InstrSSE.td

Evan Cheng evan.cheng at apple.com
Thu Apr 6 16:24:09 PDT 2006



Changes in directory llvm/lib/Target/X86:

X86ISelLowering.cpp updated: 1.158 -> 1.159
X86ISelLowering.h updated: 1.52 -> 1.53
X86InstrSSE.td updated: 1.64 -> 1.65
---
Log message:

- movlp{s|d} and movhp{s|d} support.
- Normalize shuffle nodes so result vector lower half elements come from the
  first vector, the rest come from the second vector. (Except for the
  exceptions :-).
- Other minor fixes.


---
Diffs of the changes:  (+206 -66)

 X86ISelLowering.cpp |  234 ++++++++++++++++++++++++++++++++++++++--------------
 X86ISelLowering.h   |    8 +
 X86InstrSSE.td      |   30 +++++-
 3 files changed, 206 insertions(+), 66 deletions(-)


Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.158 llvm/lib/Target/X86/X86ISelLowering.cpp:1.159
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.158	Wed Apr  5 18:38:46 2006
+++ llvm/lib/Target/X86/X86ISelLowering.cpp	Thu Apr  6 18:23:56 2006
@@ -1404,6 +1404,16 @@
           (GV->isExternal() && !GV->hasNotBeenReadFromBytecode()));
 }
 
+/// isUndefOrInRange - Op is either an undef node or a ConstantSDNode.  Return
+/// true if Op is undef or if its value falls within the specified range (L, H).
+static bool isUndefOrInRange(SDOperand Op, unsigned Low, unsigned Hi) {
+  if (Op.getOpcode() == ISD::UNDEF)
+    return true;
+
+  unsigned Val = cast<ConstantSDNode>(Op)->getValue();
+  return (Val >= Low && Val <= Hi);
+}
+
 /// 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) {
@@ -1491,24 +1501,17 @@
 
   unsigned NumElems = N->getNumOperands();
   if (NumElems == 2) {
-    // The only case that ought be handled by SHUFPD is
+    // The only cases that ought be handled by SHUFPD is
     // Dest { 2, 1 } <=  shuffle( Dest { 1, 0 },  Src { 3, 2 }
+    // Dest { 3, 0 } <=  shuffle( Dest { 1, 0 },  Src { 3, 2 }
     // Expect bit 0 == 1, bit1 == 2
     SDOperand Bit0 = N->getOperand(0);
-    if (Bit0.getOpcode() != ISD::UNDEF) {
-      assert(isa<ConstantSDNode>(Bit0) && "Invalid VECTOR_SHUFFLE mask!");
-      if (cast<ConstantSDNode>(Bit0)->getValue() != 1)
-        return false;
-    }
-
     SDOperand Bit1 = N->getOperand(1);
-    if (Bit1.getOpcode() != ISD::UNDEF) {
-      assert(isa<ConstantSDNode>(Bit1) && "Invalid VECTOR_SHUFFLE mask!");
-      if (cast<ConstantSDNode>(Bit1)->getValue() != 2)
-        return false;
-    }
-
-    return true;
+    if (isUndefOrInRange(Bit0, 0, 0) && isUndefOrInRange(Bit1, 3, 3))
+      return true;
+    if (isUndefOrInRange(Bit0, 1, 1) && isUndefOrInRange(Bit1, 2, 2))
+      return true;
+    return false;
   }
 
   if (NumElems != 4) return false;
@@ -1614,6 +1617,62 @@
   return true;
 }
 
+/// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}.
+bool X86::isMOVLPMask(SDNode *N) {
+  assert(N->getOpcode() == ISD::BUILD_VECTOR);
+
+  unsigned NumElems = N->getNumOperands();
+  if (NumElems != 2 && NumElems != 4)
+    return false;
+
+  for (unsigned i = 0; i < NumElems/2; ++i) {
+    SDOperand Arg = N->getOperand(i);
+    if (Arg.getOpcode() == ISD::UNDEF) continue;
+    assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
+    unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
+    if (Val != i + NumElems) return false;
+  }
+
+  for (unsigned i = NumElems/2; i < NumElems; ++i) {
+    SDOperand Arg = N->getOperand(i);
+    if (Arg.getOpcode() == ISD::UNDEF) continue;
+    assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
+    unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
+    if (Val != i) return false;
+  }
+
+  return true;
+}
+
+/// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}.
+bool X86::isMOVHPMask(SDNode *N) {
+  assert(N->getOpcode() == ISD::BUILD_VECTOR);
+
+  unsigned NumElems = N->getNumOperands();
+  if (NumElems != 2 && NumElems != 4)
+    return false;
+
+  for (unsigned i = 0; i < NumElems/2; ++i) {
+    SDOperand Arg = N->getOperand(i);
+    if (Arg.getOpcode() == ISD::UNDEF) continue;
+    assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
+    unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
+    if (Val != i) return false;
+  }
+
+  for (unsigned i = 0; i < NumElems/2; ++i) {
+    SDOperand Arg = N->getOperand(i + NumElems/2);
+    if (Arg.getOpcode() == ISD::UNDEF) continue;
+    assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
+    unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
+    if (Val != i + NumElems) return false;
+  }
+
+  return true;
+}
+
 /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
 /// specifies a shuffle of elements that is suitable for input to UNPCKL.
 bool X86::isUNPCKLMask(SDNode *N) {
@@ -1786,42 +1845,6 @@
   return Mask;
 }
 
-/// NormalizeVectorShuffle - Swap vector_shuffle operands (as well as
-/// values in ther permute mask if needed. Use V1 as second vector if it is
-/// undef. Return an empty SDOperand is it is already well formed.
-static SDOperand NormalizeVectorShuffle(SDOperand Op, SelectionDAG &DAG) {
-  SDOperand V1 = Op.getOperand(0);
-  SDOperand V2 = Op.getOperand(1);
-  SDOperand Mask = Op.getOperand(2);
-  MVT::ValueType VT = Op.getValueType();
-  unsigned NumElems = Mask.getNumOperands();
-  SDOperand Half1 = Mask.getOperand(0);
-  SDOperand Half2 = Mask.getOperand(NumElems/2);
-  bool V2Undef = false;
-  if (V2.getOpcode() == ISD::UNDEF) {
-    V2Undef = true;
-    V2 = V1;
-  }
-
-  if (cast<ConstantSDNode>(Half1)->getValue() >= NumElems &&
-      cast<ConstantSDNode>(Half2)->getValue() <  NumElems) {
-    // Swap the operands and change mask.
-    std::vector<SDOperand> MaskVec;
-    for (unsigned i = NumElems / 2; i != NumElems; ++i)
-      MaskVec.push_back(Mask.getOperand(i));
-    for (unsigned i = 0; i != NumElems / 2; ++i)
-      MaskVec.push_back(Mask.getOperand(i));
-    Mask =
-      DAG.getNode(ISD::BUILD_VECTOR, Mask.getValueType(), MaskVec);
-    return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V2, V1, Mask);
-  }
-
-  if (V2Undef)
-    return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1, Mask);
-
-  return Op;
-}
-
 /// isPSHUFHW_PSHUFLWMask - true if the specified VECTOR_SHUFFLE operand
 /// specifies a 8 element shuffle that can be broken into a pair of
 /// PSHUFHW and PSHUFLW.
@@ -1854,6 +1877,81 @@
   return true;
 }
 
+/// CommuteVectorShuffle - Swap vector_shuffle operandsas well as
+/// values in ther permute mask.
+static SDOperand CommuteVectorShuffle(SDOperand Op, SelectionDAG &DAG) {
+  SDOperand V1 = Op.getOperand(0);
+  SDOperand V2 = Op.getOperand(1);
+  SDOperand Mask = Op.getOperand(2);
+  MVT::ValueType VT = Op.getValueType();
+  MVT::ValueType MaskVT = Mask.getValueType();
+  MVT::ValueType EltVT = MVT::getVectorBaseType(MaskVT);
+  unsigned NumElems = Mask.getNumOperands();
+  std::vector<SDOperand> MaskVec;
+
+  for (unsigned i = 0; i != NumElems; ++i) {
+    SDOperand Arg = Mask.getOperand(i);
+    if (Arg.getOpcode() == ISD::UNDEF) continue;
+    assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
+    unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
+    if (Val < NumElems)
+      MaskVec.push_back(DAG.getConstant(Val + NumElems, EltVT));
+    else
+      MaskVec.push_back(DAG.getConstant(Val - NumElems, EltVT));
+  }
+
+  Mask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
+  return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V2, V1, Mask);
+}
+
+/// isScalarLoadToVector - Returns true if the node is a scalar load that
+/// is promoted to a vector.
+static inline bool isScalarLoadToVector(SDOperand Op) {
+  if (Op.getOpcode() == ISD::SCALAR_TO_VECTOR) {
+    Op = Op.getOperand(0);
+    return (Op.getOpcode() == ISD::LOAD);
+  }
+  return false;
+}
+
+/// ShouldXformedToMOVLP - Return true if the node should be transformed to
+/// match movlp{d|s}. The lower half elements should come from V1 (and in
+/// order), and the upper half elements should come from the upper half of
+/// V2 (not necessarily in order). And since V1 will become the source of
+/// the MOVLP, it must be a scalar load.
+static bool ShouldXformedToMOVLP(SDOperand V1, SDOperand V2, SDOperand Mask) {
+  if (isScalarLoadToVector(V1)) {
+    unsigned NumElems = Mask.getNumOperands();
+    for (unsigned i = 0, e = NumElems/2; i != e; ++i)
+      if (!isUndefOrInRange(Mask.getOperand(i), i, i))
+        return false;
+    for (unsigned i = NumElems/2; i != NumElems; ++i)
+      if (!isUndefOrInRange(Mask.getOperand(i),
+                            NumElems+NumElems/2, NumElems*2-1))
+        return false;
+    return true;
+  }
+
+  return false;
+}
+
+/// isLowerFromV2UpperFromV1 - Returns true if the shuffle mask is except
+/// the reverse of what x86 shuffles want. x86 shuffles requires the lower
+/// half elements to come from vector 1 (which would equal the dest.) and
+/// the upper half to come from vector 2.
+static bool isLowerFromV2UpperFromV1(SDOperand Op) {
+  assert(Op.getOpcode() == ISD::BUILD_VECTOR);
+
+  unsigned NumElems = Op.getNumOperands();
+  for (unsigned i = 0, e = NumElems/2; i != e; ++i)
+    if (!isUndefOrInRange(Op.getOperand(i), NumElems, NumElems*2-1))
+      return false;
+  for (unsigned i = NumElems/2; i != NumElems; ++i)
+    if (!isUndefOrInRange(Op.getOperand(i), 0, NumElems-1))
+      return false;
+  return true;
+}
+
 /// LowerOperation - Provide custom lowering hooks for some operations.
 ///
 SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
@@ -2638,23 +2736,35 @@
     MVT::ValueType VT = Op.getValueType();
     unsigned NumElems = PermMask.getNumOperands();
 
-    // Splat && PSHUFD's 2nd vector must be undef.
-    if (X86::isSplatMask(PermMask.Val)) {
-      if (V2.getOpcode() != ISD::UNDEF)
-        return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1,
-                           DAG.getNode(ISD::UNDEF, V1.getValueType()),PermMask);
+    if (X86::isSplatMask(PermMask.Val))
       return Op;
+
+    // Normalize the node to match x86 shuffle ops if needed
+    if (V2.getOpcode() != ISD::UNDEF) {
+      bool DoSwap = false;
+
+      if (ShouldXformedToMOVLP(V1, V2, PermMask))
+        DoSwap = true;
+      else if (isLowerFromV2UpperFromV1(PermMask))
+        DoSwap = true;
+
+      if (DoSwap) {
+        Op = CommuteVectorShuffle(Op, DAG);
+        V1 = Op.getOperand(0);
+        V2 = Op.getOperand(1);
+        PermMask = Op.getOperand(2);
+      }
     }
 
+    if (NumElems == 2)
+      return Op;
+
     if (X86::isUNPCKLMask(PermMask.Val) ||
         X86::isUNPCKL_v_undef_Mask(PermMask.Val) ||
         X86::isUNPCKHMask(PermMask.Val))
       // Leave the VECTOR_SHUFFLE alone. It matches {P}UNPCKL*.
       return Op;
 
-    if (NumElems == 2)
-      return NormalizeVectorShuffle(Op, DAG);
-
     // If VT is integer, try PSHUF* first, then SHUFP*.
     if (MVT::isInteger(VT)) {
       if (X86::isPSHUFDMask(PermMask.Val) ||
@@ -2667,7 +2777,7 @@
       }
 
       if (X86::isSHUFPMask(PermMask.Val))
-        return NormalizeVectorShuffle(Op, DAG);
+        return Op;
 
       // Handle v8i16 shuffle high / low shuffle node pair.
       if (VT == MVT::v8i16 && isPSHUFHW_PSHUFLWMask(PermMask.Val)) {
@@ -2691,7 +2801,7 @@
     } else {
       // Floating point cases in the other order.
       if (X86::isSHUFPMask(PermMask.Val))
-        return NormalizeVectorShuffle(Op, DAG);
+        return Op;
       if (X86::isPSHUFDMask(PermMask.Val) ||
           X86::isPSHUFHWMask(PermMask.Val) ||
           X86::isPSHUFLWMask(PermMask.Val)) {
@@ -2870,8 +2980,8 @@
     case Intrinsic::x86_sse2_ucomigt_sd:
     case Intrinsic::x86_sse2_ucomige_sd:
     case Intrinsic::x86_sse2_ucomineq_sd: {
-      unsigned Opc;
-      ISD::CondCode CC;
+      unsigned Opc = 0;
+      ISD::CondCode CC = ISD::SETCC_INVALID;
       switch (IntNo) {
         default: break;
         case Intrinsic::x86_sse_comieq_ss: 


Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.52 llvm/lib/Target/X86/X86ISelLowering.h:1.53
--- llvm/lib/Target/X86/X86ISelLowering.h:1.52	Wed Apr  5 18:38:46 2006
+++ llvm/lib/Target/X86/X86ISelLowering.h	Thu Apr  6 18:23:56 2006
@@ -212,6 +212,14 @@
    /// specifies a shuffle of elements that is suitable for input to MOVHLPS.
    bool isMOVHLPSMask(SDNode *N);
 
+   /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand
+   /// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}.
+   bool isMOVLPMask(SDNode *N);
+
+   /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand
+   /// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}.
+   bool isMOVHPMask(SDNode *N);
+
    /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
    /// specifies a shuffle of elements that is suitable for input to UNPCKL.
    bool isUNPCKLMask(SDNode *N);


Index: llvm/lib/Target/X86/X86InstrSSE.td
diff -u llvm/lib/Target/X86/X86InstrSSE.td:1.64 llvm/lib/Target/X86/X86InstrSSE.td:1.65
--- llvm/lib/Target/X86/X86InstrSSE.td:1.64	Wed Apr  5 20:49:20 2006
+++ llvm/lib/Target/X86/X86InstrSSE.td	Thu Apr  6 18:23:56 2006
@@ -96,6 +96,14 @@
   return X86::isMOVHLPSMask(N);
 }]>;
 
+def MOVHP_shuffle_mask : PatLeaf<(build_vector), [{
+  return X86::isMOVHPMask(N);
+}]>;
+
+def MOVLP_shuffle_mask : PatLeaf<(build_vector), [{
+  return X86::isMOVLPMask(N);
+}]>;
+
 def UNPCKL_shuffle_mask : PatLeaf<(build_vector), [{
   return X86::isUNPCKLMask(N);
 }]>;
@@ -712,17 +720,29 @@
 
 let isTwoAddress = 1 in {
 def MOVLPSrm : PSI<0x12, MRMSrcMem, (ops VR128:$dst, VR128:$src1, f64mem:$src2),
-                   "movlps {$src2, $dst|$dst, $src2}", []>;
+                   "movlps {$src2, $dst|$dst, $src2}",
+                   [(set VR128:$dst, 
+                     (v4f32 (vector_shuffle VR128:$src1,
+                     (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))),
+                             MOVLP_shuffle_mask)))]>;
 def MOVLPDrm : PDI<0x12, MRMSrcMem, (ops VR128:$dst, VR128:$src1, f64mem:$src2),
-                   "movlpd {$src2, $dst|$dst, $src2}", []>;
+                   "movlpd {$src2, $dst|$dst, $src2}",
+                   [(set VR128:$dst, 
+                     (v2f64 (vector_shuffle VR128:$src1,
+                             (scalar_to_vector (loadf64 addr:$src2)),
+                             MOVLP_shuffle_mask)))]>;
 def MOVHPSrm : PSI<0x16, MRMSrcMem, (ops VR128:$dst, VR128:$src1, f64mem:$src2),
-                   "movhps {$src2, $dst|$dst, $src2}", []>;
+                   "movhps {$src2, $dst|$dst, $src2}",
+                   [(set VR128:$dst, 
+                     (v4f32 (vector_shuffle VR128:$src1,
+                     (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))),
+                             MOVHP_shuffle_mask)))]>;
 def MOVHPDrm : PDI<0x16, MRMSrcMem, (ops VR128:$dst, VR128:$src1, f64mem:$src2),
                    "movhpd {$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst, 
                      (v2f64 (vector_shuffle VR128:$src1,
                              (scalar_to_vector (loadf64 addr:$src2)),
-                             UNPCKL_shuffle_mask)))]>;
+                             MOVHP_shuffle_mask)))]>;
 }
 
 def MOVLPSmr : PSI<0x13, MRMDestMem, (ops f64mem:$dst, VR128:$src),
@@ -1706,6 +1726,8 @@
       Requires<[HasSSE2]>;
 def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>,
       Requires<[HasSSE2]>;
+def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>,
+      Requires<[HasSSE2]>;
 
 // Zeroing a VR128 then do a MOVS* to the lower bits.
 def : Pat<(v2f64 (X86zexts2vec FR64:$src)),






More information about the llvm-commits mailing list