Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -268,11 +268,6 @@ SDValue PromoteExtend(SDValue Op); bool PromoteLoad(SDValue Op); - void ExtendSetCCUses(const SmallVectorImpl &SetCCs, - SDValue OrigLoad, SDValue ExtLoad, - const SDLoc &DL, - ISD::NodeType ExtType); - /// Call the node-specific routine that knows how to fold each /// particular type of node. If that doesn't do anything, try the /// target-specific DAG combines. @@ -593,6 +588,11 @@ EVT getSetCCResultType(EVT VT) const { return TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT); } + + void ExtendSetCCUses(const SmallVectorImpl &SetCCs, + SDValue OrigLoad, SDValue ExtLoad, + const SDLoc &DL, + ISD::NodeType ExtType); }; /// This class is a DAGUpdateListener that removes any deleted @@ -7699,6 +7699,48 @@ return DAG.getNode(ISD::VSELECT, DL, VT, SetCC, CastA, CastB); } +// fold ([s|z]ext (load x)) -> ([s|z]ext (truncate ([s|z]extload x))) +// Only generate vector extloads when 1) they're legal, and 2) they are +// deemed desirable by the target. +static SDValue tryToFoldSZExtLoad(SelectionDAG &DAG, DAGCombiner &Combiner, + const TargetLowering &TLI, EVT VT, + bool LegalOperations, SDNode *N, SDValue N0, + SDLoc DL, ISD::LoadExtType ExtLoadType, + ISD::NodeType ExtOpc) { + if (!ISD::isNON_EXTLoad(N0.getNode()) || + !ISD::isUNINDEXEDLoad(N0.getNode()) || + ((LegalOperations || VT.isVector() || + cast(N0)->isVolatile()) && + !TLI.isLoadExtLegal(ExtLoadType, VT, N0.getValueType()))) + return {}; + + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ExtOpc, SetCCs, TLI); + if (VT.isVector()) + DoXform &= TLI.isVectorLoadExtDesirable(SDValue(N, 0)); + if (!DoXform) + return {}; + + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = + DAG.getExtLoad(ExtLoadType, DL, VT, LN0->getChain(), LN0->getBasePtr(), + N0.getValueType(), LN0->getMemOperand()); + Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, DL, ExtOpc); + // If the load value is used only by N, replace it via CombineTo N. + bool NoReplaceTrunc = SDValue(LN0, 0).hasOneUse(); + Combiner.CombineTo(N, ExtLoad); + if (NoReplaceTrunc) { + DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1)); + } else { + SDValue Trunc = + DAG.getNode(ISD::TRUNCATE, SDLoc(N0), N0.getValueType(), ExtLoad); + Combiner.CombineTo(LN0, Trunc, ExtLoad.getValue(1)); + } + return SDValue(N, 0); // Return N so it doesn't get rechecked! +} + SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { SDValue N0 = N->getOperand(0); EVT VT = N->getValueType(0); @@ -7763,39 +7805,11 @@ } } - // fold (sext (load x)) -> (sext (truncate (sextload x))) - // Only generate vector extloads when 1) they're legal, and 2) they are - // deemed desirable by the target. - if (ISD::isNON_EXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && - ((!LegalOperations && !VT.isVector() && - !cast(N0)->isVolatile()) || - TLI.isLoadExtLegal(ISD::SEXTLOAD, VT, N0.getValueType()))) { - bool DoXform = true; - SmallVector SetCCs; - if (!N0.hasOneUse()) - DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ISD::SIGN_EXTEND, SetCCs, - TLI); - if (VT.isVector()) - DoXform &= TLI.isVectorLoadExtDesirable(SDValue(N, 0)); - if (DoXform) { - LoadSDNode *LN0 = cast(N0); - SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, DL, VT, LN0->getChain(), - LN0->getBasePtr(), N0.getValueType(), - LN0->getMemOperand()); - ExtendSetCCUses(SetCCs, N0, ExtLoad, DL, ISD::SIGN_EXTEND); - // If the load value is used only by N, replace it via CombineTo N. - bool NoReplaceTrunc = SDValue(LN0, 0).hasOneUse(); - CombineTo(N, ExtLoad); - if (NoReplaceTrunc) { - DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1)); - } else { - SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SDLoc(N0), - N0.getValueType(), ExtLoad); - CombineTo(LN0, Trunc, ExtLoad.getValue(1)); - } - return SDValue(N, 0); - } - } + // Try to fold (sext (load x)) to a smaller sextload. + if (SDValue foldedExtLoad = + tryToFoldSZExtLoad(DAG, *this, TLI, VT, LegalOperations, N, N0, DL, + ISD::SEXTLOAD, ISD::SIGN_EXTEND)) + return foldedExtLoad; // fold (sext (load x)) to multiple smaller sextloads. // Only on illegal but splittable vectors.