aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lld/MachO/SectionPriorities.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lld/MachO/SectionPriorities.cpp')
-rw-r--r--contrib/llvm-project/lld/MachO/SectionPriorities.cpp108
1 files changed, 57 insertions, 51 deletions
diff --git a/contrib/llvm-project/lld/MachO/SectionPriorities.cpp b/contrib/llvm-project/lld/MachO/SectionPriorities.cpp
index 35510d7338e8..ac4878343ac0 100644
--- a/contrib/llvm-project/lld/MachO/SectionPriorities.cpp
+++ b/contrib/llvm-project/lld/MachO/SectionPriorities.cpp
@@ -16,6 +16,7 @@
#include "InputFiles.h"
#include "Symbols.h"
#include "Target.h"
+
#include "lld/Common/Args.h"
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/ErrorHandler.h"
@@ -33,7 +34,12 @@ using namespace llvm::sys;
using namespace lld;
using namespace lld::macho;
+PriorityBuilder macho::priorityBuilder;
+
namespace {
+
+size_t highestAvailablePriority = std::numeric_limits<size_t>::max();
+
struct Edge {
int from;
uint64_t weight;
@@ -58,7 +64,7 @@ struct Cluster {
class CallGraphSort {
public:
- CallGraphSort();
+ CallGraphSort(const MapVector<SectionPair, uint64_t> &profile);
DenseMap<const InputSection *, size_t> run();
@@ -71,13 +77,9 @@ private:
constexpr int MAX_DENSITY_DEGRADATION = 8;
} // end anonymous namespace
-using SectionPair = std::pair<const InputSection *, const InputSection *>;
-
-// Take the edge list in config->callGraphProfile, resolve symbol names to
-// Symbols, and generate a graph between InputSections with the provided
-// weights.
-CallGraphSort::CallGraphSort() {
- MapVector<SectionPair, uint64_t> &profile = config->callGraphProfile;
+// Take the edge list in callGraphProfile, resolve symbol names to Symbols, and
+// generate a graph between InputSections with the provided weights.
+CallGraphSort::CallGraphSort(const MapVector<SectionPair, uint64_t> &profile) {
DenseMap<const InputSection *, int> secToCluster;
auto getOrCreateCluster = [&](const InputSection *isec) -> int {
@@ -90,7 +92,7 @@ CallGraphSort::CallGraphSort() {
};
// Create the graph
- for (std::pair<SectionPair, uint64_t> &c : profile) {
+ for (const std::pair<SectionPair, uint64_t> &c : profile) {
const auto fromSec = c.first.first->canonical();
const auto toSec = c.first.second->canonical();
uint64_t weight = c.second;
@@ -208,7 +210,7 @@ DenseMap<const InputSection *, size_t> CallGraphSort::run() {
// priority 0 and be placed at the end of sections.
// NB: This is opposite from COFF/ELF to be compatible with the existing
// order-file code.
- int curOrder = clusters.size();
+ int curOrder = highestAvailablePriority;
for (int leader : sorted) {
for (int i = leader;;) {
orderMap[sections[i]] = curOrder--;
@@ -247,8 +249,17 @@ DenseMap<const InputSection *, size_t> CallGraphSort::run() {
return orderMap;
}
-static size_t getSymbolPriority(const SymbolPriorityEntry &entry,
- const InputFile *f) {
+Optional<size_t> macho::PriorityBuilder::getSymbolPriority(const Defined *sym) {
+ if (sym->isAbsolute())
+ return None;
+
+ auto it = priorities.find(sym->getName());
+ if (it == priorities.end())
+ return None;
+ const SymbolPriorityEntry &entry = it->second;
+ const InputFile *f = sym->isec->getFile();
+ if (!f)
+ return entry.anyObjectFile;
// We don't use toString(InputFile *) here because it returns the full path
// for object files, and we only want the basename.
StringRef filename;
@@ -260,8 +271,9 @@ static size_t getSymbolPriority(const SymbolPriorityEntry &entry,
return std::max(entry.objectFiles.lookup(filename), entry.anyObjectFile);
}
-void macho::extractCallGraphProfile() {
+void macho::PriorityBuilder::extractCallGraphProfile() {
TimeTraceScope timeScope("Extract call graph profile");
+ bool hasOrderFile = !priorities.empty();
for (const InputFile *file : inputFiles) {
auto *obj = dyn_cast_or_null<ObjFile>(file);
if (!obj)
@@ -271,15 +283,17 @@ void macho::extractCallGraphProfile() {
entry.toIndex < obj->symbols.size());
auto *fromSym = dyn_cast_or_null<Defined>(obj->symbols[entry.fromIndex]);
auto *toSym = dyn_cast_or_null<Defined>(obj->symbols[entry.toIndex]);
-
- if (!fromSym || !toSym)
- continue;
- config->callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count;
+ if (fromSym && toSym &&
+ (!hasOrderFile ||
+ (!getSymbolPriority(fromSym) && !getSymbolPriority(toSym))))
+ callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count;
}
}
}
-void macho::parseOrderFile(StringRef path) {
+void macho::PriorityBuilder::parseOrderFile(StringRef path) {
+ assert(callGraphProfile.empty() &&
+ "Order file must be parsed before call graph profile is processed");
Optional<MemoryBufferRef> buffer = readFile(path);
if (!buffer) {
error("Could not read order file at " + path);
@@ -287,7 +301,6 @@ void macho::parseOrderFile(StringRef path) {
}
MemoryBufferRef mbref = *buffer;
- size_t priority = std::numeric_limits<size_t>::max();
for (StringRef line : args::getLines(mbref)) {
StringRef objectFile, symbol;
line = line.take_until([](char c) { return c == '#'; }); // ignore comments
@@ -322,49 +335,42 @@ void macho::parseOrderFile(StringRef path) {
symbol = line.trim();
if (!symbol.empty()) {
- SymbolPriorityEntry &entry = config->priorities[symbol];
+ SymbolPriorityEntry &entry = priorities[symbol];
if (!objectFile.empty())
- entry.objectFiles.insert(std::make_pair(objectFile, priority));
+ entry.objectFiles.insert(
+ std::make_pair(objectFile, highestAvailablePriority));
else
- entry.anyObjectFile = std::max(entry.anyObjectFile, priority);
+ entry.anyObjectFile =
+ std::max(entry.anyObjectFile, highestAvailablePriority);
}
- --priority;
+ --highestAvailablePriority;
}
}
-// Sort sections by the profile data provided by __LLVM,__cg_profile sections.
-//
-// 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.
-static DenseMap<const InputSection *, size_t> computeCallGraphProfileOrder() {
- TimeTraceScope timeScope("Call graph profile sort");
- return CallGraphSort().run();
-}
-
-// Each section gets assigned the priority of the highest-priority symbol it
-// contains.
-DenseMap<const InputSection *, size_t> macho::buildInputSectionPriorities() {
- if (config->callGraphProfileSort)
- return computeCallGraphProfileOrder();
+DenseMap<const InputSection *, size_t>
+macho::PriorityBuilder::buildInputSectionPriorities() {
DenseMap<const InputSection *, size_t> sectionPriorities;
+ if (config->callGraphProfileSort) {
+ // Sort sections by the profile data provided by __LLVM,__cg_profile
+ // sections.
+ //
+ // 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.
+ TimeTraceScope timeScope("Call graph profile sort");
+ sectionPriorities = CallGraphSort(callGraphProfile).run();
+ }
- if (config->priorities.empty())
+ if (priorities.empty())
return sectionPriorities;
- auto addSym = [&](Defined &sym) {
- if (sym.isAbsolute())
+ auto addSym = [&](const Defined *sym) {
+ Optional<size_t> symbolPriority = getSymbolPriority(sym);
+ if (!symbolPriority)
return;
-
- auto it = config->priorities.find(sym.getName());
- if (it == config->priorities.end())
- return;
-
- SymbolPriorityEntry &entry = it->second;
- size_t &priority = sectionPriorities[sym.isec];
- priority =
- std::max(priority, getSymbolPriority(entry, sym.isec->getFile()));
+ size_t &priority = sectionPriorities[sym->isec];
+ priority = std::max(priority, symbolPriority.getValue());
};
// TODO: Make sure this handles weak symbols correctly.
@@ -372,7 +378,7 @@ DenseMap<const InputSection *, size_t> macho::buildInputSectionPriorities() {
if (isa<ObjFile>(file))
for (Symbol *sym : file->symbols)
if (auto *d = dyn_cast_or_null<Defined>(sym))
- addSym(*d);
+ addSym(d);
}
return sectionPriorities;