forked from OSchip/llvm-project
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:
parent
0294e33ea4
commit
d37c13154a
|
@ -123,7 +123,9 @@ namespace ISD {
|
||||||
// Simple abstract vector operators. Unlike the integer and floating point
|
// Simple abstract vector operators. Unlike the integer and floating point
|
||||||
// binary operators, these nodes also take two additional operands:
|
// binary operators, these nodes also take two additional operands:
|
||||||
// a constant element count, and a value type node indicating the type of
|
// 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,
|
VADD, VSUB, VMUL,
|
||||||
|
|
||||||
// MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
|
// MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
|
||||||
|
|
|
@ -1121,6 +1121,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||||
|
|
||||||
case Expand:
|
case Expand:
|
||||||
SDOperand Lo, Hi;
|
SDOperand Lo, Hi;
|
||||||
|
unsigned IncrementSize;
|
||||||
ExpandOp(Node->getOperand(1), Lo, Hi);
|
ExpandOp(Node->getOperand(1), Lo, Hi);
|
||||||
|
|
||||||
if (!TLI.isLittleEndian())
|
if (!TLI.isLittleEndian())
|
||||||
|
@ -1128,7 +1129,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||||
|
|
||||||
Lo = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Lo, Tmp2,
|
Lo = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Lo, Tmp2,
|
||||||
Node->getOperand(3));
|
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,
|
Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
|
||||||
getIntPtrConstant(IncrementSize));
|
getIntPtrConstant(IncrementSize));
|
||||||
assert(isTypeLegal(Tmp2.getValueType()) &&
|
assert(isTypeLegal(Tmp2.getValueType()) &&
|
||||||
|
@ -3001,8 +3011,9 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
|
||||||
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
|
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
|
||||||
SDNode *Node = Op.Val;
|
SDNode *Node = Op.Val;
|
||||||
assert(getTypeAction(VT) == Expand && "Not an expanded type!");
|
assert(getTypeAction(VT) == Expand && "Not an expanded type!");
|
||||||
assert(MVT::isInteger(VT) && "Cannot expand FP values!");
|
assert((MVT::isInteger(VT) || VT == MVT::Vector) &&
|
||||||
assert(MVT::isInteger(NVT) && NVT < VT &&
|
"Cannot expand FP values!");
|
||||||
|
assert(((MVT::isInteger(NVT) && NVT < VT) || VT == MVT::Vector) &&
|
||||||
"Cannot expand to FP value or to larger int value!");
|
"Cannot expand to FP value or to larger int value!");
|
||||||
|
|
||||||
// See if we already expanded it.
|
// See if we already expanded it.
|
||||||
|
@ -3107,6 +3118,71 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
|
||||||
std::swap(Lo, Hi);
|
std::swap(Lo, Hi);
|
||||||
break;
|
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::TAILCALL:
|
||||||
case ISD::CALL: {
|
case ISD::CALL: {
|
||||||
SDOperand Chain = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
SDOperand Chain = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
||||||
|
|
|
@ -1106,7 +1106,7 @@ SDOperand SelectionDAG::getVecLoad(unsigned Count, MVT::ValueType EVT,
|
||||||
Ops.push_back(SV);
|
Ops.push_back(SV);
|
||||||
std::vector<MVT::ValueType> VTs;
|
std::vector<MVT::ValueType> VTs;
|
||||||
VTs.reserve(2);
|
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);
|
return getNode(ISD::VLOAD, VTs, Ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -528,7 +528,7 @@ void SelectionDAGLowering::visitBinary(User &I, unsigned IntOp, unsigned FPOp,
|
||||||
} else {
|
} else {
|
||||||
SDOperand Num = DAG.getConstant(NumElements, MVT::i32);
|
SDOperand Num = DAG.getConstant(NumElements, MVT::i32);
|
||||||
SDOperand Typ = DAG.getValueType(PVT);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue