Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -450,10 +450,11 @@ /// This is a helper function for MergeConsecutiveStores. When the source /// elements of the consecutive stores are all constants or all extracted /// vector elements, try to merge them into one larger store. - /// \return True if a merged store was created. - bool MergeStoresOfConstantsOrVecElts(SmallVectorImpl &StoreNodes, - EVT MemVT, unsigned NumStores, - bool IsConstantSrc, bool UseVector); + /// \return number of stores that were merged into a merged store (always + /// a prefix of \p StoreNode). + unsigned MergeStoresOfConstantsOrVecElts( + SmallVectorImpl &StoreNodes, EVT MemVT, unsigned NumStores, + bool IsConstantSrc, bool UseVector); /// This is a helper function for MergeConsecutiveStores. /// Stores that may be merged are placed in StoreNodes. @@ -470,8 +471,10 @@ /// Merge consecutive store operations into a wide store. /// This optimization uses wide integers or vectors when possible. - /// \return True if some memory operations were changed. - bool MergeConsecutiveStores(StoreSDNode *N); + /// \return number of stores that were merged into a merged store (the + /// affected nodes are stored as a prefix in \p StoreNodes). + unsigned MergeConsecutiveStores(StoreSDNode *N, + SmallVectorImpl &StoreNodes); /// \brief Try to transform a truncation where C is a constant: /// (trunc (and X, C)) -> (and (trunc X), (trunc C)) @@ -11379,12 +11382,12 @@ return DAG.getBuildVector(Ty, SL, BuildVector); } -bool DAGCombiner::MergeStoresOfConstantsOrVecElts( +unsigned DAGCombiner::MergeStoresOfConstantsOrVecElts( SmallVectorImpl &StoreNodes, EVT MemVT, unsigned NumStores, bool IsConstantSrc, bool UseVector) { // Make sure we have something to merge. if (NumStores < 2) - return false; + return 0; int64_t ElementSizeBytes = MemVT.getSizeInBits() / 8; LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode; @@ -11504,7 +11507,7 @@ } } - return true; + return NumStores; } void DAGCombiner::getStoreMergeAndAliasCandidates( @@ -11646,9 +11649,10 @@ return true; } -bool DAGCombiner::MergeConsecutiveStores(StoreSDNode* St) { +unsigned DAGCombiner::MergeConsecutiveStores( + StoreSDNode* St, SmallVectorImpl &StoreNodes) { if (OptLevel == CodeGenOpt::None) - return false; + return 0; EVT MemVT = St->getMemoryVT(); int64_t ElementSizeBytes = MemVT.getSizeInBits() / 8; @@ -11657,10 +11661,10 @@ // This function cannot currently deal with non-byte-sized memory sizes. if (ElementSizeBytes * 8 != MemVT.getSizeInBits()) - return false; + return 0; if (!MemVT.isSimple()) - return false; + return 0; // Perform an early exit check. Do not bother looking at stored values that // are not constants, loads, or extracted vector elements. @@ -11672,18 +11676,18 @@ StoredVal.getOpcode() == ISD::EXTRACT_SUBVECTOR); if (!IsConstantSrc && !IsLoadSrc && !IsExtractVecSrc) - return false; + return 0; // Don't merge vectors into wider vectors if the source data comes from loads. // TODO: This restriction can be lifted by using logic similar to the // ExtractVecSrc case. if (MemVT.isVector() && IsLoadSrc) - return false; + return 0; // Only look at ends of store sequences. SDValue Chain = SDValue(St, 0); if (Chain->hasOneUse() && Chain->use_begin()->getOpcode() == ISD::STORE) - return false; + return 0; // Save the LoadSDNodes that we find in the chain. // We need to make sure that these nodes do not interfere with @@ -11691,19 +11695,17 @@ SmallVector AliasLoadNodes; // Save the StoreSDNodes that we find in the chain. - SmallVector StoreNodes; - getStoreMergeAndAliasCandidates(St, StoreNodes, AliasLoadNodes); // Check if there is anything to merge. if (StoreNodes.size() < 2) - return false; + return 0; // only do dependence check in AA case bool UseAA = CombinerAA.getNumOccurrences() > 0 ? CombinerAA : DAG.getSubtarget().useAA(); if (UseAA && !checkMergeStoreCandidatesForDependencies(StoreNodes)) - return false; + return 0; // Sort the memory operands according to their distance from the // base pointer. As a secondary criteria: make sure stores coming @@ -11831,7 +11833,7 @@ // consecutive loads). if (StoreValOpcode != ISD::EXTRACT_VECTOR_ELT && StoreValOpcode != ISD::EXTRACT_SUBVECTOR) - return false; + return 0; // Find a legal type for the vector store. unsigned Elts = i + 1; @@ -11898,14 +11900,14 @@ } if (LoadNodes.size() < 2) - return false; + return 0; // If we have load/store pair instructions and we only have two values, // don't bother. unsigned RequiredAlignment; if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) && St->getAlignment() >= RequiredAlignment) - return false; + return 0; LoadSDNode *FirstLoad = cast(LoadNodes[0].MemNode); unsigned FirstLoadAS = FirstLoad->getAddressSpace(); @@ -11979,7 +11981,7 @@ NumElem = std::min(LastLegalType, NumElem); if (NumElem < 2) - return false; + return 0; // Collect the chains from all merged stores. SmallVector MergeStoreChains; @@ -12051,7 +12053,7 @@ } } - return true; + return NumElem; } SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST, SDValue BetterChain) { @@ -12296,14 +12298,27 @@ if (!LegalTypes) { bool EverChanged = false; - do { + for (;;) { // There can be multiple store sequences on the same chain. // Keep trying to merge store sequences until we are unable to do so // or until we merge the last store on the chain. - bool Changed = MergeConsecutiveStores(ST); - EverChanged |= Changed; - if (!Changed) break; - } while (ST->getOpcode() != ISD::DELETED_NODE); + SmallVector StoreNodes; + unsigned NumChanged = MergeConsecutiveStores(ST, StoreNodes); + if (!NumChanged) + break; + + EverChanged = true; + + bool ChangedST = false; + for (unsigned i = 0; i < NumChanged; ++i) { + if (StoreNodes[i].MemNode == ST) { + ChangedST = true; + break; + } + } + if (ChangedST) + break; + } if (EverChanged) return SDValue(N, 0);