Index: lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -723,6 +723,7 @@ SDValue WidenVecRes_UNDEF(SDNode *N); SDValue WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N); SDValue WidenVecRes_VSETCC(SDNode* N); + SDValue WidenVSELECT_SETCC(SDNode *N); SDValue WidenVecRes_Ternary(SDNode *N); SDValue WidenVecRes_Binary(SDNode *N); Index: lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -2826,6 +2826,58 @@ WidenVT, N->getOperand(0)); } +SDValue DAGTypeLegalizer::WidenVSELECT_SETCC(SDNode *N) { + LLVMContext &Ctx = *DAG.getContext(); + SDValue Cond = N->getOperand(0); + + if (N->getOpcode() != ISD::VSELECT || Cond->getOpcode() != ISD::SETCC) + return SDValue(); + + // Make a new SETCC node, with a legal VT. + EVT SetccVT = getSetCCResultType(Cond->getOperand(0).getValueType()); + if (getTypeAction(SetccVT) == TargetLowering::TypeWidenVector) + SetccVT = TLI.getTypeToTransformTo(Ctx, SetccVT); + Cond = DAG.getNode(ISD::SETCC, SDLoc(Cond), SetccVT, + Cond->getOperand(0), Cond->getOperand(1), Cond->getOperand(2)); + + // Get the widened VT for the VSELECT, and its widened operands. + EVT VSelVT = N->getValueType(0); + assert (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector); + VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT); + SDValue VSelOp1 = GetWidenedVector(N->getOperand(1)); + SDValue VSelOp2 = GetWidenedVector(N->getOperand(2)); + + // The mask of the VSELECT should have integer elements. + EVT MaskVT = VSelVT; + if (!MaskVT.getScalarType().isInteger()) + MaskVT = MaskVT.changeVectorElementTypeToInteger(); + + // After widening, the new SetCCVT and MaskVT types may not have the same + // VTs. Handle as needed with vector sign extension or truncatation. + SDValue Mask; + if (SetccVT == MaskVT) + Mask = Cond; + else if (SetccVT.getScalarSizeInBits() < MaskVT.getScalarSizeInBits()) + Mask = DAG.getSignExtendVectorInReg(Cond, SDLoc(N), MaskVT); + else { + // SetccVT has wider elements: truncate. + EVT SubVT = + EVT::getVectorVT(Ctx, MaskVT.getVectorElementType(), + SetccVT.getVectorNumElements()); + SDValue TruncCC = DAG.getNode(ISD::TRUNCATE, SDLoc(N), SubVT, Cond); + + unsigned NumSubVecs = VSelVT.getVectorNumElements() / SubVT.getVectorNumElements(); + SmallVector SubConcatOps(NumSubVecs); + SubConcatOps[0] = TruncCC; + for (unsigned i = 1; i < NumSubVecs; ++i) + SubConcatOps[i] = DAG.getUNDEF(SubVT); + + Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), MaskVT, SubConcatOps); + } + + return DAG.getNode(ISD::VSELECT, SDLoc(N), VSelVT, Mask, VSelOp1, VSelOp2); +} + SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) { EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); unsigned WidenNumElts = WidenVT.getVectorNumElements(); @@ -2833,6 +2885,9 @@ SDValue Cond1 = N->getOperand(0); EVT CondVT = Cond1.getValueType(); if (CondVT.isVector()) { + if (SDValue Res = WidenVSELECT_SETCC(N)) + return Res; + EVT CondEltVT = CondVT.getVectorElementType(); EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenNumElts); Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2846,6 +2846,7 @@ } case ISD::SIGN_EXTEND: + case ISD::SIGN_EXTEND_VECTOR_INREG: Tmp = VTBits - Op.getOperand(0).getScalarValueSizeInBits(); return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp; @@ -3044,6 +3045,68 @@ for (unsigned i = 1, e = Op.getNumOperands(); (i < e) && (Tmp > 1); ++i) Tmp = std::min(Tmp, ComputeNumSignBits(Op.getOperand(i), Depth + 1)); return Tmp; + case ISD::VECTOR_SHUFFLE: { + const ShuffleVectorSDNode *SVN = cast(Op); + unsigned Min = UINT_MAX; + unsigned NumElts = VT.getVectorNumElements(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + for (unsigned i = 0; i != NumElts && Min > 1; ++i) { + int M = SVN->getMaskElt(i); + if (M < 0) + return 1; + if ((unsigned)M < NumElts) + Tmp = ComputeNumSignBits(LHS.getOperand((unsigned)M), Depth + 1); + else + Tmp = ComputeNumSignBits(RHS.getOperand((unsigned)M - NumElts), + Depth + 1); + if (Tmp < Min) + Min = Tmp; + } + return (Min != UINT_MAX ? Min : 1); + } + case ISD::BUILD_VECTOR: { + unsigned Min = UINT_MAX; + for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) { + if (Op.getOperand(i).isUndef()) + continue; + if (Op.getOperand(i).getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + SDValue Extr = Op.getOperand(i); + // EXTRACT_VECTOR_ELT may produce an any-ext:ed result, while + // BUILD_VECTOR may in turn truncate its inserted operands. + unsigned ExtrOpBits = Extr.getOperand(0).getScalarValueSizeInBits(); + if (ExtrOpBits >= VTBits) { + Tmp = ComputeNumSignBits(Extr.getOperand(0), Depth + 1); + if (ExtrOpBits > VTBits) { + unsigned BitsDiff = ExtrOpBits - VTBits; + Tmp = ((Tmp > BitsDiff) ? (Tmp - BitsDiff) : 1); + } + } + else + return 1; + } + else + Tmp = ComputeNumSignBits(Op.getOperand(i), Depth + 1); + + if (Tmp < Min) + Min = Tmp; + } + return (Min != UINT_MAX ? Min : 1); + } + case ISD::BITCAST: + if (VT.isVector()) { + EVT OpTy = Op.getOperand(0).getValueType(); + unsigned OpBits = OpTy.getScalarType().getSizeInBits(); + if (OpTy.isVector() && OpTy.isInteger() && OpBits >= VTBits) { + // This is a cast to a vector type with smaller elements. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth + 1); + // If all bits are sign bits, this should be a SETCC result when the + // boolean contents is zero or negative one. In that case, consider + // all bits of the narrower elements to be sign bits also. + if (Tmp == OpBits) + return VTBits; + } + } } // If we are looking at the loaded value of the SDNode.