Pull some code out into a helper function.

Effeciently codegen even splats in the range [-32,30].

This allows us to codegen <30,30,30,30> as:

        vspltisw v0, 15
        vadduwm v2, v0, v0

instead of as a cp load.

llvm-svn: 27750
This commit is contained in:
Chris Lattner 2006-04-17 06:00:21 +00:00
parent 78ab345316
commit 72a67a5b1f

View File

@ -1041,6 +1041,23 @@ static bool isConstantSplat(const uint64_t Bits128[2],
return true;
}
/// BuildSplatI - Build a canonical splati of Val with an element size of
/// SplatSize. Cast the result to VT.
static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT,
SelectionDAG &DAG) {
assert(Val >= -16 && Val <= 15 && "vsplti is out of range!");
static const MVT::ValueType VTys[] = { // canonical VT to use for each size.
MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
};
MVT::ValueType CanonicalVT = VTys[SplatSize-1];
// Build a canonical splat for this value.
SDOperand Elt = DAG.getConstant(Val, MVT::getVectorBaseType(CanonicalVT));
std::vector<SDOperand> Ops(MVT::getVectorNumElements(CanonicalVT), Elt);
SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, Ops);
return DAG.getNode(ISD::BIT_CONVERT, VT, Res);
}
// If this is a case we can't handle, return null and let the default
// expansion code take care of it. If we CAN select this case, and if it
// selects to a single instruction, return Op. Otherwise, if we can codegen
@ -1079,21 +1096,14 @@ static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
// 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);
if (SextVal >= -16 && SextVal <= 15) {
const MVT::ValueType VTys[] = { // canonical VT to use for each size.
MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
};
MVT::ValueType CanonicalVT = VTys[SplatSize-1];
if (SextVal >= -16 && SextVal <= 15)
return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG);
// If this is a non-canonical splat for this value,
if (Op.getValueType() != CanonicalVT || HasAnyUndefs) {
SDOperand Elt = DAG.getConstant(SplatBits,
MVT::getVectorBaseType(CanonicalVT));
std::vector<SDOperand> Ops(MVT::getVectorNumElements(CanonicalVT), Elt);
SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, Ops);
Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
}
return Op;
// If this value is in the range [-32,30] and is even, use:
// tmp = VSPLTI[bhw], result = add tmp, tmp
if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) {
Op = BuildSplatI(SextVal >> 1, SplatSize, Op.getValueType(), DAG);
return DAG.getNode(ISD::ADD, Op.getValueType(), Op, Op);
}