From: Nate Begeman Date: Tue, 22 Nov 2005 18:16:00 +0000 (+0000) Subject: Check in code to scalarize arbitrarily wide packed types for some simple X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ab48be377298bd509427a29e174cf4e305138819;p=oota-llvm.git 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24484 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index b98a3f022bf..6e6b88223d2 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -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 diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 35f401e202a..19ccfbbf47f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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(Hi.getOperand(2))->getValue(); + MVT::ValueType EVT = cast(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(Node->getOperand(2))->getValue(); + MVT::ValueType EVT = cast(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(Node->getOperand(2))->getValue(); + MVT::ValueType EVT = cast(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. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 685bdabd49f..7676ead3551 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1106,7 +1106,7 @@ SDOperand SelectionDAG::getVecLoad(unsigned Count, MVT::ValueType EVT, Ops.push_back(SV); std::vector 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); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 079b16b1f82..88116813742 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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)); } } }