X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeTypesPromote.cpp;h=2b1a29d77cccf39953c2ee9f6ed476d68b987341;hb=5b8f82e35b51bf007de07a7ca9347d804084ddf8;hp=2ff1693e89a0b39db6795b4eba593569a20f86a1;hpb=212a11c417e272cc8fd12e66cfe5110c47559e17;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp index 2ff1693e89a..2b1a29d77cc 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp @@ -50,6 +50,7 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) { case ISD::SETCC: Result = PromoteResult_SETCC(N); break; case ISD::LOAD: Result = PromoteResult_LOAD(cast(N)); break; case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break; + case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break; case ISD::AND: case ISD::OR: @@ -74,8 +75,12 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) { case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break; case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break; case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break; + + case ISD::EXTRACT_VECTOR_ELT: + Result = PromoteResult_EXTRACT_VECTOR_ELT(N); + break; } - + // If Result is null, the sub-method took care of registering the result. if (Result.Val) SetPromotedOp(SDOperand(N, ResNo), Result); @@ -181,9 +186,10 @@ SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) { } SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) { - assert(isTypeLegal(TLI.getSetCCResultTy()) && "SetCC type is not legal??"); - return DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), N->getOperand(0), - N->getOperand(1), N->getOperand(2)); + assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0))) + && "SetCC type is not legal??"); + return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)), + N->getOperand(0), N->getOperand(1), N->getOperand(2)); } SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) { @@ -214,6 +220,65 @@ SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) { return DAG.getNode(ISD::OR, NVT, Lo, Hi); } +SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { + SDOperand InOp = N->getOperand(0); + MVT::ValueType InVT = InOp.getValueType(); + MVT::ValueType NInVT = TLI.getTypeToTransformTo(InVT); + MVT::ValueType OutVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case Promote: + if (MVT::getSizeInBits(OutVT) == MVT::getSizeInBits(NInVT)) + // The input promotes to the same size. Convert the promoted value. + return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp)); + break; + case Expand: + break; + case Scalarize: + // Convert the element to an integer and promote it by hand. + InOp = DAG.getNode(ISD::BIT_CONVERT, + MVT::getIntegerType(MVT::getSizeInBits(InVT)), + GetScalarizedOp(InOp)); + InOp = DAG.getNode(ISD::ANY_EXTEND, + MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp); + return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); + case Split: + // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split + // pieces of the input into integers and reassemble in the final type. + SDOperand Lo, Hi; + GetSplitOp(N->getOperand(0), Lo, Hi); + + unsigned LoBits = MVT::getSizeInBits(Lo.getValueType()); + Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo); + + unsigned HiBits = MVT::getSizeInBits(Hi.getValueType()); + Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + MVT::ValueType TargetTy = MVT::getIntegerType(MVT::getSizeInBits(OutVT)); + Hi = DAG.getNode(ISD::ANY_EXTEND, TargetTy, Hi); + Hi = DAG.getNode(ISD::SHL, TargetTy, Hi, + DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()), + TLI.getShiftAmountTy())); + Lo = DAG.getNode(ISD::ZERO_EXTEND, TargetTy, Lo); + + return DAG.getNode(ISD::BIT_CONVERT, OutVT, + DAG.getNode(ISD::OR, TargetTy, Lo, Hi)); + } + + // Otherwise, lower the bit-convert to a store/load from the stack, then + // promote the load. + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); + return PromoteResult_LOAD(cast(Op.Val)); +} + SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) { // The input may have strange things in the top bits of the registers, but // these operations don't care. They may have weird bits going out, but @@ -315,6 +380,51 @@ SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) { return DAG.getNode(ISD::CTTZ, NVT, Op); } +SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) { + MVT::ValueType OldVT = N->getValueType(0); + SDOperand OldVec = N->getOperand(0); + unsigned OldElts = MVT::getVectorNumElements(OldVec.getValueType()); + + if (OldElts == 1) { + assert(!isTypeLegal(OldVec.getValueType()) && + "Legal one-element vector of a type needing promotion!"); + // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp, + // but this would be wrong because the scalarized value may not yet have + // been processed. + return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), + GetScalarizedOp(OldVec)); + } + + // Convert to a vector half as long with an element type of twice the width, + // for example <4 x i16> -> <2 x i32>. + assert(!(OldElts & 1) && "Odd length vectors not supported!"); + MVT::ValueType NewVT = MVT::getIntegerType(2 * MVT::getSizeInBits(OldVT)); + assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT)); + + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, + MVT::getVectorType(NewVT, OldElts / 2), + OldVec); + + // Extract the element at OldIdx / 2 from the new vector. + SDOperand OldIdx = N->getOperand(1); + SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx); + + // Select the appropriate half of the element: Lo if OldIdx was even, + // Hi if it was odd. + SDOperand Lo = Elt; + SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt, + DAG.getConstant(MVT::getSizeInBits(OldVT), + TLI.getShiftAmountTy())); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); +} + //===----------------------------------------------------------------------===// // Operand Promotion //===----------------------------------------------------------------------===// @@ -357,8 +467,13 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break; case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo); + break; case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break; + + case ISD::MEMBARRIER: Res = PromoteOperand_MEMBARRIER(N); break; } // If the result is null, the sub-method took care of registering results etc. @@ -589,6 +704,30 @@ SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) { return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); } +SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(MVT::getSizeInBits(N->getOperand(1).getValueType()) >= + MVT::getSizeInBits(MVT::getVectorElementType(N->getValueType(0))) && + "Type of inserted value narrower than vector element type!"); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + GetPromotedOp(N->getOperand(1)), + N->getOperand(2)); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDOperand Idx = N->getOperand(2); + Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType()); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), Idx); +} + SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) { assert(!(OpNo & 1) && "Return values should be legally typed!"); assert((N->getNumOperands() & 1) && "Wrong number of operands!"); @@ -612,3 +751,14 @@ SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) { return DAG.UpdateNodeOperands(SDOperand (N, 0), &NewValues[0], NewValues.size()); } + +SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) { + SDOperand NewOps[6]; + NewOps[0] = N->getOperand(0); + for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { + SDOperand Flag = GetPromotedOp(N->getOperand(i)); + NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1); + } + return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps, + array_lengthof(NewOps)); +}