diff options
-rw-r--r-- | include/llvm/CodeGen/SelectionDAG.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 56 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 8 |
3 files changed, 45 insertions, 22 deletions
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 4b3f904bc6..82becca315 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -1149,7 +1149,8 @@ public: /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and /// return the low/high part. - std::pair<SDValue, SDValue> SplitVectorOperand(SDNode *N, unsigned OpNo) { + std::pair<SDValue, SDValue> SplitVectorOperand(const SDNode *N, unsigned OpNo) + { return SplitVector(N->getOperand(OpNo), SDLoc(N)); } diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 15b4ddc033..20b0981e97 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4327,6 +4327,23 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) { return SDValue(); } +static +std::pair<SDValue, SDValue> SplitVSETCC(const SDNode *N, SelectionDAG &DAG) { + SDLoc DL(N); + EVT LoVT, HiVT; + llvm::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0)); + + // Split the inputs. + SDValue Lo, Hi, LL, LH, RL, RH; + llvm::tie(LL, LH) = DAG.SplitVectorOperand(N, 0); + llvm::tie(RL, RH) = DAG.SplitVectorOperand(N, 1); + + Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2)); + Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2)); + + return std::make_pair(Lo, Hi); +} + SDValue DAGCombiner::visitVSELECT(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -4364,27 +4381,32 @@ SDValue DAGCombiner::visitVSELECT(SDNode *N) { } } - // Treat SETCC as a vector mask and promote the result type based on the - // targets expected SETCC result type. This will ensure that SETCC and VSELECT - // are both split by the type legalizer. This is done to prevent the type - // legalizer from unrolling SETCC into scalar comparions. - EVT SelectVT = N->getValueType(0); - EVT MaskVT = getSetCCResultType(SelectVT); - assert(MaskVT.isVector() && "Expected a vector type."); - if (N0.getOpcode() == ISD::SETCC && N0.getValueType() != MaskVT) { - SDLoc MaskDL(N0); + // If the VSELECT result requires splitting and the mask is provided by a + // SETCC, then split both nodes and its operands before legalization. This + // prevents the type legalizer from unrolling SETCC into scalar comparisons + // and enables future optimizations (e.g. min/max pattern matching on X86). + if (N0.getOpcode() == ISD::SETCC) { + EVT VT = N->getValueType(0); + + // Check if any splitting is required. + if (TLI.getTypeAction(*DAG.getContext(), VT) != + TargetLowering::TypeSplitVector) + return SDValue(); - // Extend the mask to the desired value type. - ISD::NodeType ExtendCode = - TargetLowering::getExtendForContent(TLI.getBooleanContents(true)); - SDValue Mask = DAG.getNode(ExtendCode, MaskDL, MaskVT, N0); + SDValue Lo, Hi, CCLo, CCHi, LL, LH, RL, RH; + llvm::tie(CCLo, CCHi) = SplitVSETCC(N0.getNode(), DAG); + llvm::tie(LL, LH) = DAG.SplitVectorOperand(N, 1); + llvm::tie(RL, RH) = DAG.SplitVectorOperand(N, 2); - AddToWorkList(Mask.getNode()); + Lo = DAG.getNode(N->getOpcode(), DL, LL.getValueType(), CCLo, LL, RL); + Hi = DAG.getNode(N->getOpcode(), DL, LH.getValueType(), CCHi, LH, RH); - SDValue LHS = N->getOperand(1); - SDValue RHS = N->getOperand(2); + // Add the new VSELECT nodes to the work list in case they need to be split + // again. + AddToWorkList(Lo.getNode()); + AddToWorkList(Hi.getNode()); - return DAG.getNode(ISD::VSELECT, DL, SelectVT, Mask, LHS, RHS); + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi); } return SDValue(); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index 9e97c49ddf..b3174fd373 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -488,11 +488,11 @@ void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDValue &Lo, SDValue Cond = N->getOperand(0); CL = CH = Cond; if (Cond.getValueType().isVector()) { - if (Cond.getOpcode() == ISD::SETCC) { - assert(Cond.getValueType() == getSetCCResultType(N->getValueType(0)) && - "Condition has not been prepared for split!"); + // Check if there are already splitted versions of the vector available and + // use those instead of splitting the mask operand again. + if (getTypeAction(Cond.getValueType()) == TargetLowering::TypeSplitVector) GetSplitVector(Cond, CL, CH); - } else + else llvm::tie(CL, CH) = DAG.SplitVector(Cond, dl); } |