diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1452,10 +1452,10 @@ replaceCommonSymbols(); StringRef orderFile = args.getLastArgValue(OPT_order_file); + PriorityBuilder::SymbolOrder orderFileData; if (!orderFile.empty()) { - PriorityBuilder::SymbolOrder symbolOrder = - priorityBuilder.parseOrderFile(orderFile); - priorityBuilder.processOrderFile(symbolOrder); + orderFileData = priorityBuilder.parseOrderFile(orderFile); + priorityBuilder.populatePriorities(orderFileData); } referenceStubBinder(); @@ -1513,7 +1513,7 @@ gatherInputSections(); if (config->callGraphProfileSort) - priorityBuilder.extractCallGraphProfile(); + priorityBuilder.extractCallGraphProfile(orderFileData); if (config->deadStrip) markLive(); diff --git a/lld/MachO/SectionPriorities.h b/lld/MachO/SectionPriorities.h --- a/lld/MachO/SectionPriorities.h +++ b/lld/MachO/SectionPriorities.h @@ -19,12 +19,13 @@ class PriorityBuilder { public: + using SymbolOrder = llvm::MapVector; // Reads every input section's call graph profile, and combines them into // callGraphProfile. If an order file is present, any edges where one or both // of the vertices are specified in the order file are discarded. - void extractCallGraphProfile(); + void extractCallGraphProfile( + const macho::PriorityBuilder::SymbolOrder &orderedSymbols); - using SymbolOrder = std::vector>; // Reads the order file at `path` into config->priorities. // // An order file has one entry per line, in the following format: @@ -43,7 +44,7 @@ // The file can also have line comments that start with '#'. SymbolOrder parseOrderFile(StringRef path) const; - void processOrderFile(const SymbolOrder &symbolOrder); + void populatePriorities(const SymbolOrder &symbolOrder); // 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 diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp --- a/lld/MachO/SectionPriorities.cpp +++ b/lld/MachO/SectionPriorities.cpp @@ -271,9 +271,10 @@ return std::max(entry.objectFiles.lookup(filename), entry.anyObjectFile); } -void macho::PriorityBuilder::extractCallGraphProfile() { +void macho::PriorityBuilder::extractCallGraphProfile( + const macho::PriorityBuilder::SymbolOrder &orderedSymbols) { TimeTraceScope timeScope("Extract call graph profile"); - bool hasOrderFile = !priorities.empty(); + bool hasOrderedSymbols = !orderedSymbols.empty(); for (const InputFile *file : inputFiles) { auto *obj = dyn_cast_or_null(file); if (!obj) @@ -283,16 +284,17 @@ entry.toIndex < obj->symbols.size()); 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)))) - continue; - callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count; + auto isOrdered = [&](const Defined *sym) { + return sym->isAbsolute() || orderedSymbols.count(sym->getName()) > 0; + }; + if (fromSym && toSym && + (!hasOrderedSymbols || (!isOrdered(fromSym) && !isOrdered(toSym)))) + callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count; } } } -std::vector> +macho::PriorityBuilder::SymbolOrder macho::PriorityBuilder::parseOrderFile(StringRef path) const { assert(callGraphProfile.empty() && "Order file must be parsed before call graph profile is processed"); @@ -338,15 +340,15 @@ symbol = line.trim(); if (!symbol.empty()) { - symbolOrder.emplace_back( - std::make_pair(StringRef(symbol), StringRef(objectFile))); + symbolOrder[symbol] = objectFile; } } return symbolOrder; } -void macho::PriorityBuilder::processOrderFile(const SymbolOrder &symbolOrder) { +void macho::PriorityBuilder::populatePriorities( + const SymbolOrder &symbolOrder) { for (const auto &symbolObjectFile : symbolOrder) { StringRef symbol = symbolObjectFile.first; StringRef objectFile = symbolObjectFile.second;