//===- CallGraphSort.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// This is based on the ELF port, see ELF/CallGraphSort.cpp for the details /// about the algorithm. /// //===----------------------------------------------------------------------===// #include "CallGraphSort.h" #include "COFFLinkerContext.h" #include "InputFiles.h" #include "SymbolTable.h" #include "Symbols.h" #include "lld/Common/ErrorHandler.h" #include <numeric> usingnamespacellvm; usingnamespacelld; usingnamespacelld::coff; namespace { struct Edge { … }; struct Cluster { … }; class CallGraphSort { … }; // Maximum amount the combined cluster density can be worse than the original // cluster to consider merging. constexpr int MAX_DENSITY_DEGRADATION = …; // Maximum cluster size in bytes. constexpr uint64_t MAX_CLUSTER_SIZE = …; } // end anonymous namespace SectionPair; // Take the edge list in Config->CallGraphProfile, resolve symbol names to // Symbols, and generate a graph between InputSections with the provided // weights. CallGraphSort::CallGraphSort(const COFFLinkerContext &ctx) : … { … } // It's bad to merge clusters which would degrade the density too much. static bool isNewDensityBad(Cluster &a, Cluster &b) { … } // 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 getLeader(std::vector<int> &leaders, int v) { … } static void mergeClusters(std::vector<Cluster> &cs, Cluster &into, int intoIdx, Cluster &from, int fromIdx) { … } // Group InputSections into clusters using the Call-Chain Clustering heuristic // then sort the clusters by density. DenseMap<const SectionChunk *, int> CallGraphSort::run() { … } // Sort sections by the profile data provided by /call-graph-ordering-file // // This first builds a call graph based on the profile data then merges sections // according to the C³ heuristic. All clusters are then sorted by a density // metric to further improve locality. DenseMap<const SectionChunk *, int> coff::computeCallGraphProfileOrder(const COFFLinkerContext &ctx) { … }