[llvm-commits] [llvm] r65899 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAGNodes.h lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/Target/PowerPC/PPCISelLowering.cpp

Bob Wilson bob.wilson at apple.com
Mon Mar 2 15:24:17 PST 2009


Author: bwilson
Date: Mon Mar  2 17:24:16 2009
New Revision: 65899

URL: http://llvm.org/viewvc/llvm-project?rev=65899&view=rev
Log:
Generalize BuildVectorSDNode::isConstantSplat to use APInts and handle
arbitrary vector sizes.  Add an optional MinSplatBits parameter to specify
a minimum for the splat element size.  Update the PPC target to use the
revised interface.

Modified:
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=65899&r1=65898&r2=65899&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Mon Mar  2 17:24:16 2009
@@ -1933,13 +1933,18 @@
 /// BUILD_VECTORs.
 class BuildVectorSDNode : public SDNode {
 public:
-  /// isConstantSplat - check if this is a constant splat, and if so, return
-  /// the splat element value in SplatBits.  Any undefined bits in that value
-  /// are set to zero, and the corresponding bits in the SplatUndef mask are
-  /// set.  The SplatSize value is set to the splat element size in bytes.
-  /// HasAnyUndefs is set to true if any bits in the vector are undefined.
-  bool isConstantSplat(unsigned &SplatBits, unsigned &SplatUndef,
-                       unsigned &SplatSize, bool &HasAnyUndefs);
+  /// isConstantSplat - Check if this is a constant splat, and if so, find the
+  /// smallest element size that splats the vector.  If MinSplatBits is
+  /// nonzero, the element size must be at least that large.  Note that the
+  /// splat element may be the entire vector (i.e., a one element vector).
+  /// Returns the splat element value in SplatValue.  Any undefined bits in
+  /// that value are zero, and the corresponding bits in the SplatUndef mask
+  /// are set.  The SplatBitSize value is set to the splat element size in
+  /// bits.  HasAnyUndefs is set to true if any bits in the vector are
+  /// undefined.
+  bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef,
+                       unsigned &SplatBitSize, bool &HasAnyUndefs,
+                       unsigned MinSplatBits = 0);
 
   static inline bool classof(const BuildVectorSDNode *) { return true; }
   static inline bool classof(const SDNode *N) {

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=65899&r1=65898&r2=65899&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Mar  2 17:24:16 2009
@@ -5555,93 +5555,64 @@
   return Val.ConstVal->getType();
 }
 
-// If this is a splat (repetition) of a value across the whole vector, return
-// the smallest size that splats it.  For example, "0x01010101010101..." is a
-// splat of 0x01, 0x0101, and 0x01010101.  We return SplatBits = 0x01 and
-// SplatSize = 1 byte.
-bool BuildVectorSDNode::isConstantSplat(unsigned &SplatBits,
-                                        unsigned &SplatUndef,
-                                        unsigned &SplatSize,
-                                        bool &HasAnyUndefs) {
-  uint64_t Bits128[2];
-  uint64_t Undef128[2];
-
-  // If this is a vector of constants or undefs, get the bits.  A bit in
-  // UndefBits is set if the corresponding element of the vector is an
-  // ISD::UNDEF value.  For undefs, the corresponding VectorBits values are
-  // zero.
-
-  // Start with zero'd results.
-  Bits128[0] = Bits128[1] = Undef128[0] = Undef128[1] = 0;
-
-  unsigned EltBitSize = getOperand(0).getValueType().getSizeInBits();
-  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue,
+                                        APInt &SplatUndef,
+                                        unsigned &SplatBitSize,
+                                        bool &HasAnyUndefs,
+                                        unsigned MinSplatBits) {
+  MVT VT = getValueType(0);
+  assert(VT.isVector() && "Expected a vector type");
+  unsigned sz = VT.getSizeInBits();
+  if (MinSplatBits > sz)
+    return false;
+
+  SplatValue = APInt(sz, 0);
+  SplatUndef = APInt(sz, 0);
+
+  // Get the bits.  Bits with undefined values (when the corresponding element
+  // of the vector is an ISD::UNDEF value) are set in SplatUndef and cleared
+  // in SplatValue.  If any of the values are not constant, give up and return
+  // false.
+  unsigned int nOps = getNumOperands();
+  assert(nOps > 0 && "isConstantSplat has 0-size build vector");
+  unsigned EltBitSize = VT.getVectorElementType().getSizeInBits();
+  for (unsigned i = 0; i < nOps; ++i) {
     SDValue OpVal = getOperand(i);
+    unsigned BitPos = i * EltBitSize;
 
-    unsigned PartNo = i >= e/2;     // In the upper 128 bits?
-    unsigned SlotNo = e/2 - (i & (e/2-1))-1;  // Which subpiece of the uint64_t.
-
-    uint64_t EltBits = 0;
-    if (OpVal.getOpcode() == ISD::UNDEF) {
-      uint64_t EltUndefBits = ~0U >> (32-EltBitSize);
-      Undef128[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
-      continue;
-    } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
-      EltBits = CN->getZExtValue() & (~0U >> (32-EltBitSize));
-    } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
-      assert(CN->getValueType(0) == MVT::f32 &&
-             "Only one legal FP vector type!");
-      EltBits = FloatToBits(CN->getValueAPF().convertToFloat());
-    } else {
-      // Nonconstant element.
+    if (OpVal.getOpcode() == ISD::UNDEF)
+      SplatUndef |= APInt::getBitsSet(sz, BitPos, BitPos +EltBitSize);
+    else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal))
+      SplatValue |= APInt(CN->getAPIntValue()).zext(sz) << BitPos;
+    else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal))
+      SplatValue |= CN->getValueAPF().bitcastToAPInt().zext(sz) << BitPos;
+     else
       return false;
-    }
-
-    Bits128[PartNo] |= EltBits << (SlotNo*EltBitSize);
   }
 
-  // Don't let undefs prevent splats from matching.  See if the top 64-bits are
-  // the same as the lower 64-bits, ignoring undefs.
-  if ((Bits128[0] & ~Undef128[1]) != (Bits128[1] & ~Undef128[0]))
-    return false;  // Can't be a splat if two pieces don't match.
-
-  uint64_t Bits64  = Bits128[0] | Bits128[1];
-  uint64_t Undef64 = Undef128[0] & Undef128[1];
-
-  // Check that the top 32-bits are the same as the lower 32-bits, ignoring
-  // undefs.
-  if ((Bits64 & (~Undef64 >> 32)) != ((Bits64 >> 32) & ~Undef64))
-    return false;  // Can't be a splat if two pieces don't match.
-
-  HasAnyUndefs = (Undef128[0] | Undef128[1]) != 0;
-
-  uint32_t Bits32  = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
-  uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
-
-  // If the top 16-bits are different than the lower 16-bits, ignoring
-  // undefs, we have an i32 splat.
-  if ((Bits32 & (~Undef32 >> 16)) != ((Bits32 >> 16) & ~Undef32)) {
-    SplatBits = Bits32;
-    SplatUndef = Undef32;
-    SplatSize = 4;
-    return true;
-  }
+  // The build_vector is all constants or undefs.  Find the smallest element
+  // size that splats the vector.
 
-  uint16_t Bits16  = uint16_t(Bits32)  | uint16_t(Bits32 >> 16);
-  uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
+  HasAnyUndefs = (SplatUndef != 0);
+  while (sz > 8) {
 
-  // If the top 8-bits are different than the lower 8-bits, ignoring
-  // undefs, we have an i16 splat.
-  if ((Bits16 & (uint16_t(~Undef16) >> 8)) != ((Bits16 >> 8) & ~Undef16)) {
-    SplatBits = Bits16;
-    SplatUndef = Undef16;
-    SplatSize = 2;
-    return true;
+    unsigned HalfSize = sz / 2;
+    APInt HighValue = APInt(SplatValue).lshr(HalfSize).trunc(HalfSize);
+    APInt LowValue = APInt(SplatValue).trunc(HalfSize);
+    APInt HighUndef = APInt(SplatUndef).lshr(HalfSize).trunc(HalfSize);
+    APInt LowUndef = APInt(SplatUndef).trunc(HalfSize);
+
+    // If the two halves do not match (ignoring undef bits), stop here.
+    if ((HighValue & ~LowUndef) != (LowValue & ~HighUndef) ||
+        MinSplatBits > HalfSize)
+      break;
+
+    SplatValue = HighValue | LowValue;
+    SplatUndef = HighUndef & LowUndef;
+   
+    sz = HalfSize;
   }
 
-  // Otherwise, we have an 8-bit splat.
-  SplatBits  = uint8_t(Bits16)  | uint8_t(Bits16 >> 8);
-  SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
-  SplatSize = 1;
+  SplatBitSize = sz;
   return true;
 }

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=65899&r1=65898&r2=65899&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Mon Mar  2 17:24:16 2009
@@ -3167,13 +3167,16 @@
   BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode());
   assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
 
-  // If this is a splat (repetition) of a value across the whole vector, return
-  // the smallest size that splats it.  For example, "0x01010101010101..." is a
-  // splat of 0x01, 0x0101, and 0x01010101.  We return SplatBits = 0x01 and
-  // SplatSize = 1 byte.
-  unsigned SplatBits, SplatUndef, SplatSize;
+  // Check if this is a splat of a constant value.
+  APInt APSplatBits, APSplatUndef;
+  unsigned SplatBitSize;
   bool HasAnyUndefs;
-  if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatSize, HasAnyUndefs)) {
+  if (BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
+                           HasAnyUndefs) &&
+      SplatBitSize <= 32) {
+    unsigned SplatBits = APSplatBits.getZExtValue();
+    unsigned SplatUndef = APSplatUndef.getZExtValue();
+    unsigned SplatSize = SplatBitSize / 8;
 
     // First, handle single instruction cases.
 
@@ -3189,7 +3192,8 @@
     }
 
     // If the sign extended value is in the range [-16,15], use VSPLTI[bhw].
-    int32_t SextVal= int32_t(SplatBits << (32-8*SplatSize)) >> (32-8*SplatSize);
+    int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >>
+                      (32-SplatBitSize));
     if (SextVal >= -16 && SextVal <= 15)
       return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl);
 
@@ -3221,7 +3225,6 @@
     }
 
     // Check to see if this is a wide variety of vsplti*, binop self cases.
-    unsigned SplatBitSize = SplatSize*8;
     static const signed char SplatCsts[] = {
       -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
       -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16





More information about the llvm-commits mailing list