Index: ELF/CallGraphSort.h =================================================================== --- ELF/CallGraphSort.h +++ ELF/CallGraphSort.h @@ -10,12 +10,12 @@ #ifndef LLD_ELF_CALL_GRAPH_SORT_H #define LLD_ELF_CALL_GRAPH_SORT_H -#include "InputSection.h" - #include "llvm/ADT/DenseMap.h" namespace lld { namespace elf { +class InputSectionBase; + llvm::DenseMap computeCallGraphProfileOrder(); } Index: ELF/CallGraphSort.cpp =================================================================== --- ELF/CallGraphSort.cpp +++ ELF/CallGraphSort.cpp @@ -29,7 +29,7 @@ using NodeIndex = std::ptrdiff_t; struct Node { - Node() {} + Node() = default; Node(const InputSectionBase *IS) { Sections.push_back(IS); Size = IS->getSize(); @@ -55,10 +55,8 @@ }; } // end anonymous namespace -typedef std::vector NodeList; -typedef std::unordered_set EdgeSet; - -static void insertOrIncrementEdge(EdgeSet &Edges, const Edge E) { +static void insertOrIncrementEdge(std::unordered_set &Edges, + const Edge E) { if (E.From == E.To) return; auto Res = Edges.insert(E); @@ -68,11 +66,11 @@ // Take the edge list in Config->CGProfile, resolve symbol names to SymbolBodys, // and generate a graph between InputSections with the provided weights. -static void buildCallGraph(NodeList &Nodes, EdgeSet &Edges) { - llvm::DenseMap SecToNode; +static void buildCallGraph(std::vector &Nodes, + std::unordered_set &Edges) { + DenseMap SecToNode; - auto GetOrCreateNode = [&Nodes, - &SecToNode](const InputSectionBase *IS) -> NodeIndex { + auto GetOrCreateNode = [&](const InputSectionBase *IS) -> NodeIndex { auto Res = SecToNode.insert(std::make_pair(IS, Nodes.size())); if (Res.second) Nodes.emplace_back(IS); @@ -83,10 +81,8 @@ for (const auto &C : Config->CGProfile) { if (C.second == 0) continue; - DefinedRegular *FromDR = - dyn_cast_or_null(Symtab->find(C.first.first)); - DefinedRegular *ToDR = - dyn_cast_or_null(Symtab->find(C.first.second)); + auto FromDR = dyn_cast_or_null(Symtab->find(C.first.first)); + auto ToDR = dyn_cast_or_null(Symtab->find(C.first.second)); if (!FromDR || !ToDR) continue; auto FromSB = dyn_cast_or_null(FromDR->Section); @@ -102,7 +98,8 @@ // Group InputSections into clusters using the Call-Chain Clustering heuristic // then sort the clusters by density. -static void generateClusters(NodeList &Nodes, EdgeSet &Edges) { +static void generateClusters(std::vector &Nodes, + std::unordered_set &Edges) { // Collapse the graph. while (!Edges.empty()) { // Find the largest edge @@ -158,9 +155,9 @@ // than the page size. All clusters are then sorted by a density metric to // further improve locality. llvm::DenseMap -lld::elf::computeCallGraphProfileOrder() { - NodeList Nodes; - EdgeSet Edges; +elf::computeCallGraphProfileOrder() { + std::vector Nodes; + std::unordered_set Edges; buildCallGraph(Nodes, Edges); generateClusters(Nodes, Edges); Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -605,18 +605,28 @@ // // ^[.*]+ [.*]+ [.*]+$ // -// It interprest the first value as an unsigned 64 bit weight, the second as +// It interprets the first value as an unsigned 64 bit weight, the second as // the symbol the call is from, and the third as the symbol the call is to. +// +// Example: +// +// 5000 c a +// 4000 c b +// 18446744073709551615 e d +// static void readCallGraphProfile(MemoryBufferRef MB) { - std::vector Lines = getLines(MB); - for (StringRef L : Lines) { + for (StringRef L : getLines(MB)) { SmallVector Fields; L.split(Fields, ' '); - if (Fields.size() != 3) - fatal("parse error"); + if (Fields.size() != 3) { + error("parse error"); + return; + } uint64_t Count; - if (!to_integer(Fields[0], Count)) - fatal("parse error"); + if (!to_integer(Fields[0], Count)) { + error("parse error"); + return; + } StringRef From = Fields[1]; StringRef To = Fields[2]; Config->CGProfile[std::make_pair(From, To)] = Count; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -913,15 +913,18 @@ Script->fabricateDefaultCommands(); - llvm::DenseMap OrderMap = - computeCallGraphProfileOrder(); - - for (BaseCommand *Base : Script->Opt.Commands) { - auto *OS = dyn_cast(Base); - if (!OS || OS->Name != ".text") - continue; - OS->sort([&](InputSectionBase *IS) { return OrderMap.lookup(IS); }); - break; + // Use the rarely used option -callgraph-ordering-file to sort sections. + if (!Config->CGProfile.empty()) { + llvm::DenseMap OrderMap = + computeCallGraphProfileOrder(); + + for (BaseCommand *Base : Script->Opt.Commands) { + auto *OS = dyn_cast(Base); + if (!OS || OS->Name != ".text") + continue; + OS->sort([&](InputSectionBase *IS) { return OrderMap.lookup(IS); }); + break; + } } sortBySymbolsOrder();