Index: ELF/CallGraphSort.cpp =================================================================== --- ELF/CallGraphSort.cpp +++ ELF/CallGraphSort.cpp @@ -46,6 +46,9 @@ #include "SymbolTable.h" #include "Symbols.h" +#include +#include + using namespace llvm; using namespace lld; using namespace lld::elf; @@ -68,7 +71,7 @@ return double(Weight) / double(Size); } - std::vector Sections; + std::list Sections; size_t Size = 0; uint64_t Weight = 0; uint64_t InitialWeight = 0; @@ -155,12 +158,21 @@ return false; } +// Find the leader of V's belonged cluster (represented as an equivalence +// class). We apply union-find path-halving technique (simple to implement) in +// the meantime as it decreases depths and the time complexity. +static int findLeader(std::vector &Leaders, int V) { + while (Leaders[V] != V) { + Leaders[V] = Leaders[Leaders[V]]; + V = Leaders[V]; + } + return V; +} + static void mergeClusters(Cluster &Into, Cluster &From) { - Into.Sections.insert(Into.Sections.end(), From.Sections.begin(), - From.Sections.end()); + Into.Sections.splice(Into.Sections.end(), From.Sections); Into.Size += From.Size; Into.Weight += From.Weight; - From.Sections.clear(); From.Size = 0; From.Weight = 0; } @@ -169,13 +181,10 @@ // then sort the clusters by density. void CallGraphSort::groupClusters() { std::vector SortedSecs(Clusters.size()); - std::vector SecToCluster(Clusters.size()); - - for (size_t I = 0; I < Clusters.size(); ++I) { - SortedSecs[I] = I; - SecToCluster[I] = &Clusters[I]; - } + std::vector Leaders(Clusters.size()); + std::iota(Leaders.begin(), Leaders.end(), 0); + std::iota(SortedSecs.begin(), SortedSecs.end(), 0); std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) { return Clusters[B].getDensity() < Clusters[A].getDensity(); }); @@ -183,27 +192,25 @@ for (int SI : SortedSecs) { // Clusters[SI] is the same as SecToClusters[SI] here because it has not // been merged into another cluster yet. - Cluster &C = Clusters[SI]; + int L = findLeader(Leaders, SI); + Cluster &C = Clusters[L]; // Don't consider merging if the edge is unlikely. if (C.BestPred.From == -1 || C.BestPred.Weight * 10 <= C.InitialWeight) continue; - Cluster *PredC = SecToCluster[C.BestPred.From]; - if (PredC == &C) + int PredL = findLeader(Leaders, C.BestPred.From); + if (L == PredL) continue; + Cluster *PredC = &Clusters[PredL]; if (C.Size + PredC->Size > MAX_CLUSTER_SIZE) continue; if (isNewDensityBad(*PredC, C)) continue; - // NOTE: Consider using a disjoint-set to track section -> cluster mapping - // if this is ever slow. - for (int SI : C.Sections) - SecToCluster[SI] = PredC; - + Leaders[L] = PredL; mergeClusters(*PredC, C); }