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,60 @@ 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 an updated ValueType. This may need to be + // widened, if so it must be done now. + 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)); + + // Make a new widened VSELECT node. + 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)); + + // We want the mask of the VSELECT to have an integer vector with the same + // number of bits as its result (and arguments) vector type. + EVT MaskVT = VSelVT; + if (!MaskVT.getScalarType().isInteger()) + MaskVT = MaskVT.changeVectorElementTypeToInteger(); + + // After widening, the new SetCCVT and MaskVT types may not have the same + // element type, but we know that the number of defined elements are the + // same. Handle as needed with 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 { + 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 +2887,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; @@ -3038,12 +3039,57 @@ case ISD::EXTRACT_SUBVECTOR: return ComputeNumSignBits(Op.getOperand(0), Depth + 1); case ISD::CONCAT_VECTORS: + case ISD::VECTOR_SHUFFLE: // Determine the minimum number of sign bits across all input vectors. // Early out if the result is already 1. Tmp = ComputeNumSignBits(Op.getOperand(0), Depth + 1); 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::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) { + // FIXME: Use a set and only do the recursive calls on unique source + // vectors (this is called many times for different elements of same + // vector). + 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) : 0); + } + } + else + return 0; + } + else + Tmp = ComputeNumSignBits(Op.getOperand(i), Depth + 1); + + if (Tmp < Min) + Min = Tmp; + } + return Min; + } + case ISD::BITCAST: + if (VT.isVector()) { + unsigned OpBits = Op.getOperand(0).getScalarValueSizeInBits(); + if (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.