diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1454,7 +1454,6 @@ StringRef orderFile = args.getLastArgValue(OPT_order_file); if (!orderFile.empty()) { priorityBuilder.parseOrderFile(orderFile); - priorityBuilder.populatePriorities(); } referenceStubBinder(); diff --git a/lld/MachO/SectionPriorities.h b/lld/MachO/SectionPriorities.h --- a/lld/MachO/SectionPriorities.h +++ b/lld/MachO/SectionPriorities.h @@ -42,8 +42,6 @@ // The file can also have line comments that start with '#'. void parseOrderFile(StringRef path); - void populatePriorities(); - // Returns layout priorities for some or all input sections. Sections are laid // out in decreasing order; that is, a higher priority section will be closer // to the beginning of its output section. @@ -57,30 +55,16 @@ // contains. llvm::DenseMap buildInputSectionPriorities(); -private: - // The symbol with the highest priority should be ordered first in the output - // section (modulo input section contiguity constraints). Using priority - // (highest first) instead of order (lowest first) has the convenient property - // that the default-constructed zero priority -- for symbols/sections without - // a user-defined order -- naturally ends up putting them at the end of the - // output. - struct SymbolPriorityEntry { - // The priority given to a matching symbol, regardless of which object file - // it originated from. - size_t anyObjectFile = 0; - // The priority given to a matching symbol from a particular object file. - llvm::DenseMap objectFiles; - }; - - llvm::Optional getSymbolPriority(const Defined *sym); - bool isOrdered(const Defined *sym); - using SymbolObjectFile = std::pair; using SymbolOrder = std::vector; + +private: + bool isOrdered(const Defined &sym); + // This will be populated with symbols ordered so that the earlier // symbols will have higher priority than the later symbols. SymbolOrder inputOrder; - llvm::DenseMap priorities; + std::set inputSet; llvm::MapVector callGraphProfile; }; diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp --- a/lld/MachO/SectionPriorities.cpp +++ b/lld/MachO/SectionPriorities.cpp @@ -37,9 +37,24 @@ PriorityBuilder macho::priorityBuilder; namespace { - +struct SymbolPriorityEntry; +using SymbolPriorites = llvm::DenseMap; size_t highestAvailablePriority = std::numeric_limits::max(); +// The symbol with the highest priority should be ordered first in the output +// section (modulo input section contiguity constraints). Using priority +// (highest first) instead of order (lowest first) has the convenient property +// that the default-constructed zero priority -- for symbols/sections without +// a user-defined order -- naturally ends up putting them at the end of the +// output. +struct SymbolPriorityEntry { + // The priority given to a matching symbol, regardless of which object file + // it originated from. + size_t anyObjectFile = 0; + // The priority given to a matching symbol from a particular object file. + llvm::DenseMap objectFiles; +}; + struct Edge { int from; uint64_t weight; @@ -249,7 +264,8 @@ return orderMap; } -Optional macho::PriorityBuilder::getSymbolPriority(const Defined *sym) { +Optional getSymbolPriority(const SymbolPriorites &priorities, + const Defined *sym) { if (sym->isAbsolute()) return None; @@ -271,9 +287,13 @@ return std::max(entry.objectFiles.lookup(filename), entry.anyObjectFile); } +bool macho::PriorityBuilder::isOrdered(const Defined &sym) { + return sym.isAbsolute() || inputSet.find(sym.getName()) != inputSet.end(); +} + void macho::PriorityBuilder::extractCallGraphProfile() { TimeTraceScope timeScope("Extract call graph profile"); - bool hasOrderFile = !priorities.empty(); + bool hasInputOrder = !inputOrder.empty(); for (const InputFile *file : inputFiles) { auto *obj = dyn_cast_or_null(file); if (!obj) @@ -284,8 +304,7 @@ auto *fromSym = dyn_cast_or_null(obj->symbols[entry.fromIndex]); auto *toSym = dyn_cast_or_null(obj->symbols[entry.toIndex]); if (fromSym && toSym && - (!hasOrderFile || - (!getSymbolPriority(fromSym) && !getSymbolPriority(toSym)))) + (!hasInputOrder || (!isOrdered(*fromSym) && !isOrdered(*toSym)))) callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count; } } @@ -336,11 +355,14 @@ if (!symbol.empty()) { inputOrder.push_back(std::make_pair(symbol.str(), objectFile.str())); + inputSet.insert(inputOrder.back().first); } } } -void macho::PriorityBuilder::populatePriorities() { +static SymbolPriorites +populatePriorities(const PriorityBuilder::SymbolOrder &inputOrder) { + SymbolPriorites priorities; for (const auto &symbolObjectFile : inputOrder) { StringRef symbol = symbolObjectFile.first; StringRef objectFile = symbolObjectFile.second; @@ -354,10 +376,12 @@ --highestAvailablePriority; } + return priorities; } DenseMap macho::PriorityBuilder::buildInputSectionPriorities() { + SymbolPriorites priorities = populatePriorities(inputOrder); DenseMap sectionPriorities; if (config->callGraphProfileSort) { // Sort sections by the profile data provided by __LLVM,__cg_profile @@ -374,7 +398,7 @@ return sectionPriorities; auto addSym = [&](const Defined *sym) { - Optional symbolPriority = getSymbolPriority(sym); + Optional symbolPriority = getSymbolPriority(priorities, sym); if (!symbolPriority.hasValue()) return; size_t &priority = sectionPriorities[sym->isec];