Index: llvm/trunk/include/llvm/CodeGen/TargetLowering.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLowering.h +++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h @@ -3647,6 +3647,13 @@ /// Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs. SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const; + /// Expand CTTZ/CTTZ_ZERO_UNDEF nodes. Expands vector/scalar CTTZ nodes, + /// vector nodes can only succeed if all operations are legal/custom. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandCTTZ(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + /// Turn load of vector type into a load of the individual elements. /// \param LD load to expand /// \returns MERGE_VALUEs of the scalar loads with their chains. Index: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2789,35 +2789,6 @@ Op = DAG.getNOT(dl, Op, VT); return DAG.getNode(ISD::CTPOP, dl, VT, Op); } - case ISD::CTTZ_ZERO_UNDEF: - // This trivially expands to CTTZ. - return DAG.getNode(ISD::CTTZ, dl, VT, Op); - case ISD::CTTZ: { - if (TLI.isOperationLegalOrCustom(ISD::CTTZ_ZERO_UNDEF, VT)) { - EVT SetCCVT = getSetCCResultType(VT); - SDValue CTTZ = DAG.getNode(ISD::CTTZ_ZERO_UNDEF, dl, VT, Op); - SDValue Zero = DAG.getConstant(0, dl, VT); - SDValue SrcIsZero = DAG.getSetCC(dl, SetCCVT, Op, Zero, ISD::SETEQ); - return DAG.getNode(ISD::SELECT, dl, VT, SrcIsZero, - DAG.getConstant(Len, dl, VT), CTTZ); - } - - // for now, we use: { return popcount(~x & (x - 1)); } - // unless the target has ctlz but not ctpop, in which case we use: - // { return 32 - nlz(~x & (x-1)); } - // Ref: "Hacker's Delight" by Henry Warren - SDValue Tmp3 = DAG.getNode(ISD::AND, dl, VT, - DAG.getNOT(dl, Op, VT), - DAG.getNode(ISD::SUB, dl, VT, Op, - DAG.getConstant(1, dl, VT))); - // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. - if (!TLI.isOperationLegal(ISD::CTPOP, VT) && - TLI.isOperationLegal(ISD::CTLZ, VT)) - return DAG.getNode(ISD::SUB, dl, VT, - DAG.getConstant(Len, dl, VT), - DAG.getNode(ISD::CTLZ, dl, VT, Tmp3)); - return DAG.getNode(ISD::CTPOP, dl, VT, Tmp3); - } } } @@ -2831,11 +2802,14 @@ case ISD::CTPOP: case ISD::CTLZ: case ISD::CTLZ_ZERO_UNDEF: - case ISD::CTTZ: - case ISD::CTTZ_ZERO_UNDEF: Tmp1 = ExpandBitCount(Node->getOpcode(), Node->getOperand(0), dl); Results.push_back(Tmp1); break; + case ISD::CTTZ: + case ISD::CTTZ_ZERO_UNDEF: + if (TLI.expandCTTZ(Node, Tmp1, DAG)) + Results.push_back(Tmp1); + break; case ISD::BITREVERSE: Results.push_back(ExpandBITREVERSE(Node->getOperand(0), dl)); break; Index: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -1105,23 +1105,11 @@ SDValue VectorLegalizer::ExpandCTTZ(SDValue Op) { EVT VT = Op.getValueType(); - unsigned NumBitsPerElt = VT.getScalarSizeInBits(); - - // If the non-ZERO_UNDEF version is supported we can use that instead. - if (TLI.isOperationLegalOrCustom(ISD::CTTZ, VT)) { - SDLoc DL(Op); - return DAG.getNode(ISD::CTTZ, DL, VT, Op.getOperand(0)); - } - // If we have the appropriate vector bit operations, it is better to use them - // than unrolling and expanding each component. - if (isPowerOf2_32(NumBitsPerElt) && - (TLI.isOperationLegalOrCustom(ISD::CTPOP, VT) || - TLI.isOperationLegalOrCustom(ISD::CTLZ, VT)) && - TLI.isOperationLegalOrCustom(ISD::SUB, VT) && - TLI.isOperationLegalOrCustomOrPromote(ISD::AND, VT) && - TLI.isOperationLegalOrCustomOrPromote(ISD::XOR, VT)) - return Op; + // Attempt to expand using TargetLowering. + SDValue Result; + if (TLI.expandCTTZ(Op.getNode(), Result, DAG)) + return Result; // Otherwise go ahead and unroll. return DAG.UnrollVectorOp(Op.getNode()); Index: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -4142,6 +4142,61 @@ return SDValue(); } +bool TargetLowering::expandCTTZ(SDNode *Node, SDValue &Result, + SelectionDAG &DAG) const { + SDLoc dl(Node); + EVT VT = Node->getValueType(0); + SDValue Op = Node->getOperand(0); + unsigned NumBitsPerElt = VT.getScalarSizeInBits(); + + // If the non-ZERO_UNDEF version is supported we can use that instead. + if (Node->getOpcode() == ISD::CTTZ_ZERO_UNDEF && + isOperationLegalOrCustom(ISD::CTTZ, VT)) { + Result = DAG.getNode(ISD::CTTZ, dl, VT, Op); + return true; + } + + // If the ZERO_UNDEF version is supported use that and handle the zero case. + if (isOperationLegalOrCustom(ISD::CTTZ_ZERO_UNDEF, VT)) { + EVT SetCCVT = + getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT); + SDValue CTTZ = DAG.getNode(ISD::CTTZ_ZERO_UNDEF, dl, VT, Op); + SDValue Zero = DAG.getConstant(0, dl, VT); + SDValue SrcIsZero = DAG.getSetCC(dl, SetCCVT, Op, Zero, ISD::SETEQ); + Result = DAG.getNode(ISD::SELECT, dl, VT, SrcIsZero, + DAG.getConstant(NumBitsPerElt, dl, VT), CTTZ); + return true; + } + + // Only expand vector types if we have the appropriate vector bit operations. + if (VT.isVector() && (!isPowerOf2_32(NumBitsPerElt) || + (!isOperationLegalOrCustom(ISD::CTPOP, VT) && + !isOperationLegalOrCustom(ISD::CTLZ, VT)) || + !isOperationLegalOrCustom(ISD::SUB, VT) || + !isOperationLegalOrCustomOrPromote(ISD::AND, VT) || + !isOperationLegalOrCustomOrPromote(ISD::XOR, VT))) + return false; + + // for now, we use: { return popcount(~x & (x - 1)); } + // unless the target has ctlz but not ctpop, in which case we use: + // { return 32 - nlz(~x & (x-1)); } + // Ref: "Hacker's Delight" by Henry Warren + SDValue Tmp = DAG.getNode( + ISD::AND, dl, VT, DAG.getNOT(dl, Op, VT), + DAG.getNode(ISD::SUB, dl, VT, Op, DAG.getConstant(1, dl, VT))); + + // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. + if (isOperationLegal(ISD::CTLZ, VT) && !isOperationLegal(ISD::CTPOP, VT)) { + Result = + DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(NumBitsPerElt, dl, VT), + DAG.getNode(ISD::CTLZ, dl, VT, Tmp)); + return true; + } + + Result = DAG.getNode(ISD::CTPOP, dl, VT, Tmp); + return true; +} + SDValue TargetLowering::scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const { SDLoc SL(LD);