diff options
| author | Bob Wilson <bob.wilson@apple.com> | 2009-03-01 01:13:55 +0000 | 
|---|---|---|
| committer | Bob Wilson <bob.wilson@apple.com> | 2009-03-01 01:13:55 +0000 | 
| commit | d8ea0e144ec21a46cca390e1b30f5fb582272f8a (patch) | |
| tree | 69ea85321bcbd71f087b2b4bd5466f30134ec876 /llvm/lib/CodeGen | |
| parent | ed5e69fe5057c6bf9fd3165630dfb29c868843ac (diff) | |
| download | bcm5719-llvm-d8ea0e144ec21a46cca390e1b30f5fb582272f8a.tar.gz bcm5719-llvm-d8ea0e144ec21a46cca390e1b30f5fb582272f8a.zip | |
Combine PPC's GetConstantBuildVectorBits and isConstantSplat functions to a new
method in a BuildVectorSDNode "pseudo-class".
llvm-svn: 65747
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 91 | 
1 files changed, 91 insertions, 0 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 171ddbdad51..9dfd6be9d5b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5554,3 +5554,94 @@ const Type *ConstantPoolSDNode::getType() const {      return Val.MachineCPVal->getType();    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) { +    SDValue OpVal = getOperand(i); + +    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. +      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; +  } + +  uint16_t Bits16  = uint16_t(Bits32)  | uint16_t(Bits32 >> 16); +  uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16); + +  // 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; +  } + +  // 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; +  return true; +} | 

