X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeDAG.cpp;h=5866e1a9f97f233f0cb80b22991aef1eb6c4a7f5;hb=9a6b92de4c2207b427f3b9cd67cd122dafc5b6c6;hp=d03c4a275641734160c0067d393119922e6068c1;hpb=53997b07451a28582a8bb55716e13fc1bcd5c838;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d03c4a27564..5866e1a9f97 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -100,9 +100,9 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize { /// processed to the result. std::map ScalarizedNodes; - /// WidenNodes - For nodes that need to be widen from one vector type to - /// another, this contains the mapping of ones we have already widen. This - /// allows us to avoid widening more than once. + /// WidenNodes - For nodes that need to be widened from one vector type to + /// another, this contains the mapping of those that we have already widen. + /// This allows us to avoid widening more than once. std::map WidenNodes; void AddLegalizedOperand(SDValue From, SDValue To) { @@ -117,7 +117,7 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize { // If someone requests legalization of the new node, return itself. LegalizedNodes.insert(std::make_pair(To, To)); } - void AddWidenOperand(SDValue From, SDValue To) { + void AddWidenedOperand(SDValue From, SDValue To) { bool isNew = WidenNodes.insert(std::make_pair(From, To)).second; assert(isNew && "Got into the map somehow?"); // If someone requests legalization of the new node, return itself. @@ -180,13 +180,12 @@ private: /// types. void ExpandOp(SDValue O, SDValue &Lo, SDValue &Hi); - /// WidenVectorOp - Widen a vector operation in order to do the computation - /// in a wider type given to a wider type given by WidenVT (e.g., v3i32 to - /// v4i32). The produced value will have the correct value for the existing - /// elements but no guarantee is made about the new elements at the end of - /// the vector: it may be zero, sign-extended, or garbage. This is useful - /// when we have instruction operating on an illegal vector type and we want - /// to widen it to do the computation on a legal wider vector type. + /// WidenVectorOp - Widen a vector operation to a wider type given by WidenVT + /// (e.g., v3i32 to v4i32). The produced value will have the correct value + /// for the existing elements but no guarantee is made about the new elements + /// at the end of the vector: it may be zero, ones, or garbage. This is useful + /// when we have an instruction operating on an illegal vector type and we + /// want to widen it to do the computation on a legal wider vector type. SDValue WidenVectorOp(SDValue Op, MVT WidenVT); /// SplitVectorOp - Given an operand of vector type, break it down into @@ -198,7 +197,7 @@ private: /// scalar (e.g. f32) value. SDValue ScalarizeVectorOp(SDValue O); - /// Useful 16 element vector used to pass operands for widening + /// Useful 16 element vector type that is used to pass operands for widening. typedef SmallVector SDValueVector; /// LoadWidenVectorOp - Load a vector for a wider type. Returns true if @@ -2009,7 +2008,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp3 = Node->getOperand(3); // RHS Tmp4 = Node->getOperand(1); // CC - LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4); + LegalizeSetCC(TLI.getSetCCResultType(Tmp2), Tmp2, Tmp3, Tmp4); LastCALLSEQ_END = DAG.getEntryNode(); // If we didn't get both a LHS and RHS back from LegalizeSetCC, @@ -2911,7 +2910,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp4 = LegalizeOp(Node->getOperand(3)); // False SDValue CC = Node->getOperand(4); - LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC); + LegalizeSetCC(TLI.getSetCCResultType(Tmp1), Tmp1, Tmp2, CC); // If we didn't get both a LHS and RHS back from LegalizeSetCC, // the LHS is a legal SETCC itself. In this case, we need to compare @@ -3100,7 +3099,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); - + switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { default: assert(0 && "BinOp legalize operation not supported"); case TargetLowering::Legal: break; @@ -3817,7 +3816,49 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } } break; - + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + switch (CvtCode) { + default: assert(0 && "Unknown cvt code!"); + case ISD::CVT_SF: + case ISD::CVT_UF: + break; + case ISD::CVT_FF: + case ISD::CVT_FS: + case ISD::CVT_FU: + case ISD::CVT_SS: + case ISD::CVT_SU: + case ISD::CVT_US: + case ISD::CVT_UU: { + SDValue DTyOp = Node->getOperand(1); + SDValue STyOp = Node->getOperand(2); + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Expand: assert(0 && "Shouldn't need to expand other operators here!"); + case Legal: + Tmp1 = LegalizeOp(Node->getOperand(0)); + Result = DAG.UpdateNodeOperands(Result, Tmp1, DTyOp, STyOp, + RndOp, SatOp); + if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == + TargetLowering::Custom) { + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) Result = Tmp1; + } + break; + case Promote: + Result = PromoteOp(Node->getOperand(0)); + // For FP, make Op1 a i32 + + Result = DAG.getConvertRndSat(Result.getValueType(), Result, + DTyOp, STyOp, RndOp, SatOp, CvtCode); + break; + } + break; + } + } // end switch CvtCode + break; + } // Conversion operators. The source and destination have different types. case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: { @@ -4235,6 +4276,19 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { break; } break; + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) && + "can only promote integers"); + Result = DAG.getConvertRndSat(NVT, Node->getOperand(0), + Node->getOperand(1), Node->getOperand(2), + Node->getOperand(3), Node->getOperand(4), + CvtCode); + break; + + } case ISD::BIT_CONVERT: Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0), Node->getValueType(0)); @@ -7211,16 +7265,34 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Lo = Node->getOperand(0); Hi = Node->getOperand(1); } else { - SmallVector LoOps(Node->op_begin(), - Node->op_begin()+NewNumSubvectors); + SmallVector LoOps(Node->op_begin(), + Node->op_begin()+NewNumSubvectors); Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size()); - SmallVector HiOps(Node->op_begin()+NewNumSubvectors, + SmallVector HiOps(Node->op_begin()+NewNumSubvectors, Node->op_end()); Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size()); } break; } + case ISD::EXTRACT_SUBVECTOR: { + SDValue Vec = Op.getOperand(0); + SDValue Idx = Op.getOperand(1); + MVT IdxVT = Idx.getValueType(); + + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Lo, Vec, Idx); + ConstantSDNode *CIdx = dyn_cast(Idx); + if (CIdx) { + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, + DAG.getConstant(CIdx->getZExtValue() + NewNumElts_Lo, + IdxVT)); + } else { + Idx = DAG.getNode(ISD::ADD, IdxVT, Idx, + DAG.getConstant(NewNumElts_Lo, IdxVT)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, Idx); + } + break; + } case ISD::SELECT: { SDValue Cond = Node->getOperand(0); @@ -7327,6 +7399,24 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H); break; } + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + SDValue L, H; + SplitVectorOp(Node->getOperand(0), L, H); + SDValue DTyOpL = DAG.getValueType(NewVT_Lo); + SDValue DTyOpH = DAG.getValueType(NewVT_Hi); + SDValue STyOpL = DAG.getValueType(L.getValueType()); + SDValue STyOpH = DAG.getValueType(H.getValueType()); + + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + + Lo = DAG.getConvertRndSat(NewVT_Lo, L, DTyOpL, STyOpL, + RndOp, SatOp, CvtCode); + Hi = DAG.getConvertRndSat(NewVT_Hi, H, DTyOpH, STyOpH, + RndOp, SatOp, CvtCode); + break; + } case ISD::LOAD: { LoadSDNode *LD = cast(Node); SDValue Ch = LD->getChain(); @@ -7465,6 +7555,16 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { NewVT, ScalarizeVectorOp(Node->getOperand(0))); break; + case ISD::CONVERT_RNDSAT: { + SDValue Op0 = ScalarizeVectorOp(Node->getOperand(0)); + Result = DAG.getConvertRndSat(NewVT, Op0, + DAG.getValueType(NewVT), + DAG.getValueType(Op0.getValueType()), + Node->getOperand(3), + Node->getOperand(4), + cast(Node)->getCvtCode()); + break; + } case ISD::FPOWI: case ISD::FP_ROUND: Result = DAG.getNode(Node->getOpcode(), @@ -7517,8 +7617,8 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { break; } case ISD::EXTRACT_SUBVECTOR: - Result = Node->getOperand(0); - assert(Result.getValueType() == NewVT); + Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, Node->getOperand(0), + Node->getOperand(1)); break; case ISD::BIT_CONVERT: { SDValue Op0 = Op.getOperand(0); @@ -7583,8 +7683,7 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { // the legal type, the resulting code will be more efficient. If this is not // the case, the resulting code will preform badly as we end up generating // code to pack/unpack the results. It is the function that calls widen - // that is responsible for seeing this doesn't happen. For some cases, we - // have decided that it is not worth widening so we just split the operation. + // that is responsible for seeing this doesn't happen. switch (Node->getOpcode()) { default: #ifndef NDEBUG @@ -7593,8 +7692,7 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { assert(0 && "Unexpected operation in WidenVectorOp!"); break; case ISD::CopyFromReg: - assert(0 && "CopyFromReg must be legal!"); - case ISD::UNDEF: + assert(0 && "CopyFromReg doesn't need widening!"); case ISD::Constant: case ISD::ConstantFP: // To build a vector of these elements, clients should call BuildVector @@ -7604,6 +7702,9 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { // Variable Arguments with vector types doesn't make any sense to me assert(0 && "Unexpected operation in WidenVectorOp!"); break; + case ISD::UNDEF: + Result = DAG.getNode(ISD::UNDEF, WidenVT); + break; case ISD::BUILD_VECTOR: { // Build a vector with undefined for the new nodes SDValueVector NewOps(Node->op_begin(), Node->op_end()); @@ -7742,7 +7843,10 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { case ISD::FNEG: case ISD::FSQRT: case ISD::FSIN: - case ISD::FCOS: { + case ISD::FCOS: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::CTLZ: { // Unary op widening SDValue Tmp1; TargetLowering::LegalizeAction action = @@ -7765,6 +7869,44 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { } break; } + case ISD::CONVERT_RNDSAT: { + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + SDValue SrcOp = Node->getOperand(0); + + // Converts between two different types so we need to determine + // the correct widen type for the input operand. + MVT SVT = SrcOp.getValueType(); + assert(SVT.isVector() && "can not widen non vector type"); + MVT SEVT = SVT.getVectorElementType(); + MVT SWidenVT = MVT::getVectorVT(SEVT, NewNumElts); + + SrcOp = WidenVectorOp(SrcOp, SWidenVT); + assert(SrcOp.getValueType() == WidenVT); + SDValue DTyOp = DAG.getValueType(WidenVT); + SDValue STyOp = DAG.getValueType(SrcOp.getValueType()); + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + + Result = DAG.getConvertRndSat(WidenVT, SrcOp, DTyOp, STyOp, + RndOp, SatOp, CvtCode); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } case ISD::FPOW: case ISD::FPOWI: case ISD::ADD: @@ -7859,15 +8001,38 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { break; } case ISD::EXTRACT_SUBVECTOR: { - SDValue Tmp1; - - // The incoming vector might already be the proper type - if (Node->getOperand(0).getValueType() != WidenVT) - Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); - else - Tmp1 = Node->getOperand(0); - assert(Tmp1.getValueType() == WidenVT); - Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Node->getOperand(1)); + SDValue Tmp1 = Node->getOperand(0); + SDValue Idx = Node->getOperand(1); + ConstantSDNode *CIdx = dyn_cast(Idx); + if (CIdx && CIdx->getZExtValue() == 0) { + // Since we are access the start of the vector, the incoming + // vector type might be the proper. + MVT Tmp1VT = Tmp1.getValueType(); + if (Tmp1VT == WidenVT) + return Tmp1; + else { + unsigned Tmp1VTNumElts = Tmp1VT.getVectorNumElements(); + if (Tmp1VTNumElts < NewNumElts) + Result = WidenVectorOp(Tmp1, WidenVT); + else + Result = DAG.getNode(ISD::EXTRACT_SUBVECTOR, WidenVT, Tmp1, Idx); + } + } else if (NewNumElts % NumElts == 0) { + // Widen the extracted subvector. + unsigned NumConcat = NewNumElts / NumElts; + SDValue UndefVal = DAG.getNode(ISD::UNDEF, VT); + SmallVector MOps; + MOps.push_back(Op); + for (unsigned i = 1; i != NumConcat; ++i) { + MOps.push_back(UndefVal); + } + Result = LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, WidenVT, + &MOps[0], MOps.size())); + } else { + assert(0 && "can not widen extract subvector"); + // This could be implemented using insert and build vector but I would + // like to see when this happens. + } break; } @@ -8017,7 +8182,7 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { if (Result != Op) Result = LegalizeOp(Result); - AddWidenOperand(Op, Result); + AddWidenedOperand(Op, Result); return Result; } @@ -8096,7 +8261,7 @@ SDValue SelectionDAGLegalize::genWidenVectorLoads(SDValueVector& LdChain, FindWidenVecType(TLI, LdWidth, ResType, EVT, VecEVT); EVTWidth = EVT.getSizeInBits(); // Readjust position and vector position based on new load type - Idx = Idx * (oEVTWidth/EVTWidth)+1; + Idx = Idx * (oEVTWidth/EVTWidth); VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp); } @@ -8161,7 +8326,7 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain, int SVOffset, unsigned Alignment, bool isVolatile, - SDValue ValOp, + SDValue ValOp, unsigned StWidth) { // Breaks the stores into a series of power of 2 width stores. For any // width, we convert the vector to the vector of element size that we @@ -8176,7 +8341,7 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain, SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, ValOp); SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp, - DAG.getIntPtrConstant(0)); + DAG.getIntPtrConstant(0)); SDValue StOp = DAG.getStore(Chain, EOp, BasePtr, SV, SVOffset, isVolatile, Alignment); StChain.push_back(StOp); @@ -8203,12 +8368,12 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain, FindWidenVecType(TLI, StWidth, VVT, EVT, VecEVT); EVTWidth = EVT.getSizeInBits(); // Readjust position and vector position based on new load type - Idx = Idx * (oEVTWidth/EVTWidth)+1; + Idx = Idx * (oEVTWidth/EVTWidth); VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp); } EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp, - DAG.getIntPtrConstant(Idx)); + DAG.getIntPtrConstant(Idx++)); StChain.push_back(DAG.getStore(Chain, EOp, BasePtr, SV, SVOffset + Offset, isVolatile, MinAlign(Alignment, Offset)));