Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6248,6 +6248,93 @@ return CV; } + // Optimize away unnecessary extensions / truncates produced by the type + // legalizer. If a SETCC node can be found to be the sole source of the + // mask operand, use it instead and modify it here only if needed. + if (TLI.getBooleanContents(true /*isVec*/, false /*isFloat*/) == + TargetLoweringBase::ZeroOrNegativeOneBooleanContent) { + SDNode *SetCCNode = nullptr; + + // BUILD_VECTOR seems to appear when the original vector type holds less + // number of elements than half of the legal vector type with same + // element type. + if (N0->getOpcode() == ISD::BUILD_VECTOR) { + for (unsigned i = 0, e = N0->getNumOperands(); i != e; ++i) { + SDValue Op = N0->getOperand(i); + if (Op.isUndef()) + continue; + + if (Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + Op = Op.getOperand(0); + if (Op.getOpcode() == ISD::BITCAST) + Op = Op.getOperand(0); + if (Op.getOpcode() == ISD::SIGN_EXTEND_VECTOR_INREG) + Op = Op.getOperand(0); + if (Op.getOpcode() == ISD::SETCC) { + if (SetCCNode == nullptr) { + SetCCNode = Op.getNode(); + continue; + } + if (SetCCNode == Op.getNode()) + continue; + } + } + + SetCCNode = nullptr; + break; + } + } + + // VECTOR_SHUFFLE seems to appear at times when the selected elements are + // wider than those handled by SETCC. + if (N0->getOpcode()== ISD::VECTOR_SHUFFLE) { + SDValue Op = N0->getOperand(0); + if (Op.getOpcode() == ISD::BITCAST) { + Op = Op.getOperand(0); + if (Op.getOpcode() == ISD::SIGN_EXTEND_VECTOR_INREG) { + Op = Op.getOperand(0); + if (Op.getOpcode() == ISD::SETCC) + SetCCNode = Op.getNode(); + } + } + } + + if (SetCCNode != nullptr) { + EVT VT = N->getValueType(0); + EVT MaskVT = N0->getValueType(0); + SDValue Mask; + + if (SetCCNode->getValueType(0) == VT) + // If the SETCC produces already the correct type, just use it as is. + Mask = SDValue(SetCCNode, 0); + else if ((SetCCNode->getValueType(0).getScalarSizeInBits() < + VT.getScalarSizeInBits())) + // If the SETCC element type is narrower than the selected elements, a + // SIGN_EXTEND_INREG is needed for the mask. + Mask = DAG.getSignExtendVectorInReg(SDValue(SetCCNode,0), + SDLoc(N), MaskVT); + else { + // The SETCC element type is wider than the selected elements, a + // TRUNCATE concatenated with undef elemnts is needed. + EVT SubVT = + EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(), + SetCCNode->getValueType(0).getVectorNumElements()); + SDValue TruncCC = DAG.getNode(ISD::TRUNCATE, SDLoc(SetCCNode), SubVT, + SDValue(SetCCNode, 0)); + + unsigned NumSubVecs = MaskVT.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), VT, Mask, N1, N2); + } + } + return SDValue(); } @@ -7510,6 +7597,12 @@ if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1) return N0; + // No need to extend i1 if boolean contents is all one's or zero's. + if (EVTBits == 1 && + (TLI.getBooleanContents(true /*isVec*/, false /*isFloat*/) == + TargetLoweringBase::ZeroOrNegativeOneBooleanContent)) + return N0; + // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2 if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && EVT.bitsLT(cast(N0.getOperand(1))->getVT()))