Check in code to scalarize arbitrarily wide packed types for some simple

vector operations (load, add, sub, mul).

This allows us to codegen:
void %foo(<4 x float> * %a) {
entry:
  %tmp1 = load <4 x float> * %a;
  %tmp2 = add <4 x float> %tmp1, %tmp1
  store <4 x float> %tmp2, <4 x float> *%a
  ret void
}

on ppc as:
_foo:
        lfs f0, 12(r3)
        lfs f1, 8(r3)
        lfs f2, 4(r3)
        lfs f3, 0(r3)
        fadds f0, f0, f0
        fadds f1, f1, f1
        fadds f2, f2, f2
        fadds f3, f3, f3
        stfs f0, 12(r3)
        stfs f1, 8(r3)
        stfs f2, 4(r3)
        stfs f3, 0(r3)
        blr

llvm-svn: 24484
This commit is contained in:
Nate Begeman 2005-11-22 18:16:00 +00:00
parent 0294e33ea4
commit d37c13154a
4 changed files with 84 additions and 6 deletions

View File

@ -123,7 +123,9 @@ namespace ISD {
// Simple abstract vector operators. Unlike the integer and floating point
// binary operators, these nodes also take two additional operands:
// a constant element count, and a value type node indicating the type of
// the elements. The order is count, type, op0, op1.
// the elements. The order is op0, op1, count, type. All vector opcodes,
// including VLOAD, must currently have count and type as their 3rd and 4th
// arguments.
VADD, VSUB, VMUL,
// MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing

View File

@ -1121,6 +1121,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
case Expand:
SDOperand Lo, Hi;
unsigned IncrementSize;
ExpandOp(Node->getOperand(1), Lo, Hi);
if (!TLI.isLittleEndian())
@ -1128,7 +1129,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Lo = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Lo, Tmp2,
Node->getOperand(3));
unsigned IncrementSize = MVT::getSizeInBits(Hi.getValueType())/8;
// If this is a vector type, then we have to calculate the increment as
// the product of the element size in bytes, and the number of elements
// in the high half of the vector.
if (MVT::Vector == Hi.getValueType()) {
unsigned NumElems = cast<ConstantSDNode>(Hi.getOperand(2))->getValue();
MVT::ValueType EVT = cast<VTSDNode>(Hi.getOperand(3))->getVT();
IncrementSize = NumElems * MVT::getSizeInBits(EVT)/8;
} else {
IncrementSize = MVT::getSizeInBits(Hi.getValueType())/8;
}
Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
getIntPtrConstant(IncrementSize));
assert(isTypeLegal(Tmp2.getValueType()) &&
@ -3001,8 +3011,9 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
SDNode *Node = Op.Val;
assert(getTypeAction(VT) == Expand && "Not an expanded type!");
assert(MVT::isInteger(VT) && "Cannot expand FP values!");
assert(MVT::isInteger(NVT) && NVT < VT &&
assert((MVT::isInteger(VT) || VT == MVT::Vector) &&
"Cannot expand FP values!");
assert(((MVT::isInteger(NVT) && NVT < VT) || VT == MVT::Vector) &&
"Cannot expand to FP value or to larger int value!");
// See if we already expanded it.
@ -3107,6 +3118,71 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
std::swap(Lo, Hi);
break;
}
case ISD::VLOAD: {
SDOperand Ch = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
SDOperand Ptr = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
unsigned NumElements =cast<ConstantSDNode>(Node->getOperand(2))->getValue();
MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
// If we only have two elements, turn into a pair of scalar loads.
// FIXME: handle case where a vector of two elements is fine, such as
// 2 x double on SSE2.
if (NumElements == 2) {
Lo = DAG.getLoad(EVT, Ch, Ptr, Node->getOperand(4));
// Increment the pointer to the other half.
unsigned IncrementSize = MVT::getSizeInBits(EVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
//Is this safe? declaring that the two parts of the split load
//are from the same instruction?
Hi = DAG.getLoad(EVT, Ch, Ptr, Node->getOperand(4));
} else {
NumElements /= 2; // Split the vector in half
Lo = DAG.getVecLoad(NumElements, EVT, Ch, Ptr, Node->getOperand(4));
unsigned IncrementSize = NumElements * MVT::getSizeInBits(EVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
//Is this safe? declaring that the two parts of the split load
//are from the same instruction?
Hi = DAG.getVecLoad(NumElements, EVT, Ch, Ptr, Node->getOperand(4));
}
// Build a factor node to remember that this load is independent of the
// other one.
SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
Hi.getValue(1));
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), TF);
if (!TLI.isLittleEndian())
std::swap(Lo, Hi);
break;
}
case ISD::VADD:
case ISD::VSUB:
case ISD::VMUL: {
unsigned NumElements =cast<ConstantSDNode>(Node->getOperand(2))->getValue();
MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
SDOperand LL, LH, RL, RH;
ExpandOp(Node->getOperand(0), LL, LH);
ExpandOp(Node->getOperand(1), RL, RH);
// If we only have two elements, turn into a pair of scalar loads.
// FIXME: handle case where a vector of two elements is fine, such as
// 2 x double on SSE2.
if (NumElements == 2) {
unsigned Opc = getScalarizedOpcode(Node->getOpcode(), EVT);
Lo = DAG.getNode(Opc, EVT, LL, RL);
Hi = DAG.getNode(Opc, EVT, LH, RH);
} else {
Lo = DAG.getNode(Node->getOpcode(), MVT::Vector, LL, RL, LL.getOperand(2),
LL.getOperand(3));
Hi = DAG.getNode(Node->getOpcode(), MVT::Vector, LH, RH, LH.getOperand(2),
LH.getOperand(3));
}
break;
}
case ISD::TAILCALL:
case ISD::CALL: {
SDOperand Chain = LegalizeOp(Node->getOperand(0)); // Legalize the chain.

View File

@ -1106,7 +1106,7 @@ SDOperand SelectionDAG::getVecLoad(unsigned Count, MVT::ValueType EVT,
Ops.push_back(SV);
std::vector<MVT::ValueType> VTs;
VTs.reserve(2);
VTs.push_back(EVT); VTs.push_back(MVT::Other); // Add token chain.
VTs.push_back(MVT::Vector); VTs.push_back(MVT::Other); // Add token chain.
return getNode(ISD::VLOAD, VTs, Ops);
}

View File

@ -528,7 +528,7 @@ void SelectionDAGLowering::visitBinary(User &I, unsigned IntOp, unsigned FPOp,
} else {
SDOperand Num = DAG.getConstant(NumElements, MVT::i32);
SDOperand Typ = DAG.getValueType(PVT);
setValue(&I, DAG.getNode(VecOp, Op1.getValueType(), Num, Typ, Op1, Op2));
setValue(&I, DAG.getNode(VecOp, MVT::Vector, Op1, Op2, Num, Typ));
}
}
}