mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-29 15:17:14 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65899 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1933,13 +1933,18 @@ public:
|
|||||||
/// BUILD_VECTORs.
|
/// BUILD_VECTORs.
|
||||||
class BuildVectorSDNode : public SDNode {
|
class BuildVectorSDNode : public SDNode {
|
||||||
public:
|
public:
|
||||||
/// isConstantSplat - check if this is a constant splat, and if so, return
|
/// isConstantSplat - Check if this is a constant splat, and if so, find the
|
||||||
/// the splat element value in SplatBits. Any undefined bits in that value
|
/// smallest element size that splats the vector. If MinSplatBits is
|
||||||
/// are set to zero, and the corresponding bits in the SplatUndef mask are
|
/// nonzero, the element size must be at least that large. Note that the
|
||||||
/// set. The SplatSize value is set to the splat element size in bytes.
|
/// splat element may be the entire vector (i.e., a one element vector).
|
||||||
/// HasAnyUndefs is set to true if any bits in the vector are undefined.
|
/// Returns the splat element value in SplatValue. Any undefined bits in
|
||||||
bool isConstantSplat(unsigned &SplatBits, unsigned &SplatUndef,
|
/// that value are zero, and the corresponding bits in the SplatUndef mask
|
||||||
unsigned &SplatSize, bool &HasAnyUndefs);
|
/// 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 BuildVectorSDNode *) { return true; }
|
||||||
static inline bool classof(const SDNode *N) {
|
static inline bool classof(const SDNode *N) {
|
||||||
|
@@ -5555,93 +5555,64 @@ const Type *ConstantPoolSDNode::getType() const {
|
|||||||
return Val.ConstVal->getType();
|
return Val.ConstVal->getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a splat (repetition) of a value across the whole vector, return
|
bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue,
|
||||||
// the smallest size that splats it. For example, "0x01010101010101..." is a
|
APInt &SplatUndef,
|
||||||
// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
|
unsigned &SplatBitSize,
|
||||||
// SplatSize = 1 byte.
|
bool &HasAnyUndefs,
|
||||||
bool BuildVectorSDNode::isConstantSplat(unsigned &SplatBits,
|
unsigned MinSplatBits) {
|
||||||
unsigned &SplatUndef,
|
MVT VT = getValueType(0);
|
||||||
unsigned &SplatSize,
|
assert(VT.isVector() && "Expected a vector type");
|
||||||
bool &HasAnyUndefs) {
|
unsigned sz = VT.getSizeInBits();
|
||||||
uint64_t Bits128[2];
|
if (MinSplatBits > sz)
|
||||||
uint64_t Undef128[2];
|
return false;
|
||||||
|
|
||||||
// If this is a vector of constants or undefs, get the bits. A bit in
|
SplatValue = APInt(sz, 0);
|
||||||
// UndefBits is set if the corresponding element of the vector is an
|
SplatUndef = APInt(sz, 0);
|
||||||
// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
|
|
||||||
// zero.
|
|
||||||
|
|
||||||
// Start with zero'd results.
|
// Get the bits. Bits with undefined values (when the corresponding element
|
||||||
Bits128[0] = Bits128[1] = Undef128[0] = Undef128[1] = 0;
|
// 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
|
||||||
unsigned EltBitSize = getOperand(0).getValueType().getSizeInBits();
|
// false.
|
||||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
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);
|
SDValue OpVal = getOperand(i);
|
||||||
|
unsigned BitPos = i * EltBitSize;
|
||||||
|
|
||||||
unsigned PartNo = i >= e/2; // In the upper 128 bits?
|
if (OpVal.getOpcode() == ISD::UNDEF)
|
||||||
unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
|
SplatUndef |= APInt::getBitsSet(sz, BitPos, BitPos +EltBitSize);
|
||||||
|
else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal))
|
||||||
uint64_t EltBits = 0;
|
SplatValue |= APInt(CN->getAPIntValue()).zext(sz) << BitPos;
|
||||||
if (OpVal.getOpcode() == ISD::UNDEF) {
|
else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal))
|
||||||
uint64_t EltUndefBits = ~0U >> (32-EltBitSize);
|
SplatValue |= CN->getValueAPF().bitcastToAPInt().zext(sz) << BitPos;
|
||||||
Undef128[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
|
else
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bits128[PartNo] |= EltBits << (SlotNo*EltBitSize);
|
// The build_vector is all constants or undefs. Find the smallest element
|
||||||
|
// size that splats the vector.
|
||||||
|
|
||||||
|
HasAnyUndefs = (SplatUndef != 0);
|
||||||
|
while (sz > 8) {
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't let undefs prevent splats from matching. See if the top 64-bits are
|
SplatBitSize = sz;
|
||||||
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -3167,13 +3167,16 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
|||||||
BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode());
|
BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode());
|
||||||
assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
|
assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
|
||||||
|
|
||||||
// If this is a splat (repetition) of a value across the whole vector, return
|
// Check if this is a splat of a constant value.
|
||||||
// the smallest size that splats it. For example, "0x01010101010101..." is a
|
APInt APSplatBits, APSplatUndef;
|
||||||
// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
|
unsigned SplatBitSize;
|
||||||
// SplatSize = 1 byte.
|
|
||||||
unsigned SplatBits, SplatUndef, SplatSize;
|
|
||||||
bool HasAnyUndefs;
|
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.
|
// First, handle single instruction cases.
|
||||||
|
|
||||||
@@ -3189,7 +3192,8 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the sign extended value is in the range [-16,15], use VSPLTI[bhw].
|
// 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)
|
if (SextVal >= -16 && SextVal <= 15)
|
||||||
return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl);
|
return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl);
|
||||||
|
|
||||||
@@ -3221,7 +3225,6 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if this is a wide variety of vsplti*, binop self cases.
|
// Check to see if this is a wide variety of vsplti*, binop self cases.
|
||||||
unsigned SplatBitSize = SplatSize*8;
|
|
||||||
static const signed char SplatCsts[] = {
|
static const signed char SplatCsts[] = {
|
||||||
-1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
|
-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
|
-8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
|
||||||
|
Reference in New Issue
Block a user