Skip to content

Commit e23ea24

Browse files
committed
[lld] Add flag to order any section for compression
1 parent 6dad2c2 commit e23ea24

File tree

10 files changed

+168
-117
lines changed

10 files changed

+168
-117
lines changed

lld/ELF/BPSectionOrderer.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ struct BPOrdererELF : lld::BPOrderer<BPOrdererELF> {
2929
DenseMap<const InputSectionBase *, Defined *> secToSym;
3030

3131
static uint64_t getSize(const Section &sec) { return sec.getSize(); }
32-
static bool isCodeSection(const Section &sec) {
33-
return sec.flags & ELF::SHF_EXECINSTR;
32+
static std::string getSectionName(const Section &sec) {
33+
// return (sec.getSegName() + sec.getName()).str();
34+
return "TODO";
3435
}
3536
ArrayRef<Defined *> getSymbols(const Section &sec) {
3637
auto it = secToSym.find(&sec);
@@ -94,8 +95,7 @@ DenseMap<const InputSectionBase *, int> elf::runBalancedPartitioning(
9495
for (ELFFileBase *file : ctx.objectFiles)
9596
for (Symbol *sym : file->getLocalSymbols())
9697
addSection(*sym);
97-
return orderer.computeOrder(profilePath, forFunctionCompression,
98-
forDataCompression,
98+
return orderer.computeOrder(profilePath, {/*TODO*/},
9999
compressionSortStartupFunctions, verbose,
100100
sections, rootSymbolToSectionIdxs);
101101
}

lld/MachO/BPSectionOrderer.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ template <> struct lld::BPOrdererTraits<struct BPOrdererMachO> {
3131
namespace {
3232
struct BPOrdererMachO : lld::BPOrderer<BPOrdererMachO> {
3333
static uint64_t getSize(const Section &sec) { return sec.getSize(); }
34-
static bool isCodeSection(const Section &sec) {
35-
return macho::isCodeSection(&sec);
34+
static std::string getSectionName(const Section &sec) {
35+
return (sec.getSegName() + sec.getName()).str();
3636
}
3737
static ArrayRef<Defined *> getSymbols(const Section &sec) {
3838
return sec.symbols;
@@ -107,7 +107,7 @@ struct BPOrdererMachO : lld::BPOrderer<BPOrdererMachO> {
107107
} // namespace
108108

109109
DenseMap<const InputSection *, int> lld::macho::runBalancedPartitioning(
110-
StringRef profilePath, bool forFunctionCompression, bool forDataCompression,
110+
StringRef profilePath, ArrayRef<GlobPattern> compressionSortSectionGlobs,
111111
bool compressionSortStartupFunctions, bool verbose) {
112112
// Collect candidate sections and associated symbols.
113113
SmallVector<InputSection *> sections;
@@ -140,8 +140,7 @@ DenseMap<const InputSection *, int> lld::macho::runBalancedPartitioning(
140140
}
141141
}
142142

143-
return BPOrdererMachO().computeOrder(profilePath, forFunctionCompression,
144-
forDataCompression,
143+
return BPOrdererMachO().computeOrder(profilePath, compressionSortSectionGlobs,
145144
compressionSortStartupFunctions, verbose,
146145
sections, rootSymbolToSectionIdxs);
147146
}

lld/MachO/BPSectionOrderer.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
#ifndef LLD_MACHO_BPSECTION_ORDERER_H
1515
#define LLD_MACHO_BPSECTION_ORDERER_H
1616

17+
#include "llvm/ADT/ArrayRef.h"
1718
#include "llvm/ADT/DenseMap.h"
1819
#include "llvm/ADT/StringRef.h"
20+
#include "llvm/Support/GlobPattern.h"
1921

2022
namespace lld::macho {
2123
class InputSection;
@@ -25,10 +27,10 @@ class InputSection;
2527
///
2628
/// It is important that .subsections_via_symbols is used to ensure functions
2729
/// and data are in their own sections and thus can be reordered.
28-
llvm::DenseMap<const InputSection *, int>
29-
runBalancedPartitioning(llvm::StringRef profilePath,
30-
bool forFunctionCompression, bool forDataCompression,
31-
bool compressionSortStartupFunctions, bool verbose);
30+
llvm::DenseMap<const InputSection *, int> runBalancedPartitioning(
31+
llvm::StringRef profilePath,
32+
llvm::ArrayRef<llvm::GlobPattern> compressionSortSectionGlobs,
33+
bool compressionSortStartupFunctions, bool verbose);
3234

3335
} // namespace lld::macho
3436

lld/MachO/Config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ struct Configuration {
231231
llvm::StringRef irpgoProfilePath;
232232
bool bpStartupFunctionSort = false;
233233
bool bpCompressionSortStartupFunctions = false;
234-
bool bpFunctionOrderForCompression = false;
235-
bool bpDataOrderForCompression = false;
234+
std::vector<std::string> bpCompressionSortSections;
235+
llvm::SmallVector<llvm::GlobPattern> bpCompressionSortSectionGlobs;
236236
bool bpVerboseSectionOrderer = false;
237237

238238
SectionRenameMap sectionRenameMap;

lld/MachO/Driver.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,20 +2034,32 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
20342034
if (config->irpgoProfilePath.empty() && config->bpStartupFunctionSort)
20352035
error("--bp-startup-sort=function must be used with "
20362036
"--irpgo-profile");
2037+
config->bpCompressionSortSections =
2038+
args.getAllArgValues(OPT_bp_compression_sort_section);
2039+
auto addCompressionSectionGlob = [&](StringRef s) {
2040+
auto patOrErr = GlobPattern::create(s);
2041+
if (patOrErr) {
2042+
config->bpCompressionSortSectionGlobs.push_back(std::move(*patOrErr));
2043+
} else {
2044+
error("--bp-compression-sort-sections: " +
2045+
toString(patOrErr.takeError()));
2046+
}
2047+
};
2048+
for (StringRef s : config->bpCompressionSortSections)
2049+
addCompressionSectionGlob(s);
20372050
if (const Arg *arg = args.getLastArg(OPT_bp_compression_sort)) {
20382051
StringRef compressionSortStr = arg->getValue();
20392052
if (compressionSortStr == "function") {
2040-
config->bpFunctionOrderForCompression = true;
2053+
addCompressionSectionGlob("__TEXT*");
20412054
} else if (compressionSortStr == "data") {
2042-
config->bpDataOrderForCompression = true;
2055+
addCompressionSectionGlob("__DATA*");
20432056
} else if (compressionSortStr == "both") {
2044-
config->bpFunctionOrderForCompression = true;
2045-
config->bpDataOrderForCompression = true;
2057+
addCompressionSectionGlob("*");
20462058
} else if (compressionSortStr != "none") {
20472059
error("unknown value `" + compressionSortStr + "` for " +
20482060
arg->getSpelling());
20492061
}
2050-
if (compressionSortStr != "none")
2062+
if (!config->bpCompressionSortSectionGlobs.empty())
20512063
IncompatWithCGSort(arg->getSpelling());
20522064
}
20532065
config->bpVerboseSectionOrderer = args.hasArg(OPT_verbose_bp_section_orderer);

lld/MachO/Options.td

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,17 @@ def bp_compression_sort_startup_functions: Flag<["--"], "bp-compression-sort-sta
147147
Group<grp_lld>;
148148
def no_bp_compression_sort_startup_functions: Flag<["--"], "no-bp-compression-sort-startup-functions">,
149149
HelpText<"Do not order startup function for compression">, Group<grp_lld>;
150-
def bp_compression_sort: Joined<["--"], "bp-compression-sort=">,
151-
MetaVarName<"[none,function,data,both]">,
152-
HelpText<"Order sections to improve compressed size">, Group<grp_lld>;
150+
def bp_compression_sort
151+
: Joined<["--"], "bp-compression-sort=">,
152+
MetaVarName<"[none,function,data,both]">,
153+
HelpText<"Order sections to improve compressed size. Deprecated. Please "
154+
"use --bp-compression-sort-section">,
155+
Group<grp_lld>;
156+
def bp_compression_sort_section
157+
: Joined<["--"], "bp-compression-sort-section=">,
158+
MetaVarName<"<section-glob>">,
159+
HelpText<"Order <section-glob> for optimal compressed size">,
160+
Group<grp_lld>;
153161
def irpgo_profile_sort: Separate<["--"], "irpgo-profile-sort">, Group<grp_lld>;
154162
def irpgo_profile_sort_eq: Joined<["--"], "irpgo-profile-sort=">,
155163
Alias<!cast<Separate>(irpgo_profile_sort)>, MetaVarName<"<profile>">,

lld/MachO/SectionPriorities.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,12 @@ void macho::PriorityBuilder::parseOrderFile(StringRef path) {
363363
DenseMap<const InputSection *, int>
364364
macho::PriorityBuilder::buildInputSectionPriorities() {
365365
DenseMap<const InputSection *, int> sectionPriorities;
366-
if (config->bpStartupFunctionSort || config->bpFunctionOrderForCompression ||
367-
config->bpDataOrderForCompression) {
366+
if (config->bpStartupFunctionSort ||
367+
!config->bpCompressionSortSectionGlobs.empty()) {
368368
TimeTraceScope timeScope("Balanced Partitioning Section Orderer");
369369
sectionPriorities = runBalancedPartitioning(
370370
config->bpStartupFunctionSort ? config->irpgoProfilePath : "",
371-
config->bpFunctionOrderForCompression,
372-
config->bpDataOrderForCompression,
371+
config->bpCompressionSortSectionGlobs,
373372
config->bpCompressionSortStartupFunctions,
374373
config->bpVerboseSectionOrderer);
375374
} else if (config->callGraphProfileSort) {

lld/include/lld/Common/BPSectionOrdererBase.inc

Lines changed: 70 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ template <class D> struct BPOrderer {
5858
// program startup.
5959
// * compressionSortStartupFunctions: if profilePath is specified, allocate
6060
// extra utility vertices to prioritize nearby function similarity.
61-
auto computeOrder(llvm::StringRef profilePath, bool forFunctionCompression,
62-
bool forDataCompression,
63-
bool compressionSortStartupFunctions, bool verbose,
64-
llvm::ArrayRef<Section *> sections,
65-
const DenseMap<CachedHashStringRef, std::set<unsigned>>
66-
&rootSymbolToSectionIdxs)
61+
auto
62+
computeOrder(llvm::StringRef profilePath,
63+
llvm::ArrayRef<llvm::GlobPattern> compressionSortSectionGlobs,
64+
bool compressionSortStartupFunctions, bool verbose,
65+
llvm::ArrayRef<Section *> sections,
66+
const DenseMap<CachedHashStringRef, std::set<unsigned>>
67+
&rootSymbolToSectionIdxs)
6768
-> llvm::DenseMap<const Section *, int>;
6869

6970
std::optional<StringRef> static getResolvedLinkageName(StringRef name) {
@@ -150,7 +151,7 @@ static SmallVector<std::pair<unsigned, UtilityNodes>> getUnsForCompression(
150151

151152
template <class D>
152153
auto BPOrderer<D>::computeOrder(
153-
StringRef profilePath, bool forFunctionCompression, bool forDataCompression,
154+
StringRef profilePath, ArrayRef<GlobPattern> compressionSortSectionGlobs,
154155
bool compressionSortStartupFunctions, bool verbose,
155156
ArrayRef<Section *> sections,
156157
const DenseMap<CachedHashStringRef, std::set<unsigned>>
@@ -221,19 +222,20 @@ auto BPOrderer<D>::computeOrder(
221222
}
222223
}
223224

224-
SmallVector<unsigned> sectionIdxsForFunctionCompression,
225-
sectionIdxsForDataCompression;
225+
// Using map<> to guarantee that iteration order is deterministic
226+
std::map<std::string, SmallVector<unsigned>> sectionNameToIdxsForCompression;
226227
for (unsigned sectionIdx = 0; sectionIdx < sections.size(); sectionIdx++) {
227228
if (startupSectionIdxUNs.count(sectionIdx))
228229
continue;
229230
const auto *isec = sections[sectionIdx];
230-
if (D::isCodeSection(*isec)) {
231-
if (forFunctionCompression)
232-
sectionIdxsForFunctionCompression.push_back(sectionIdx);
233-
} else {
234-
if (forDataCompression)
235-
sectionIdxsForDataCompression.push_back(sectionIdx);
236-
}
231+
std::string sectionName = D::getSectionName(*isec);
232+
bool isMatch =
233+
llvm::any_of(compressionSortSectionGlobs, [&](const GlobPattern &glob) {
234+
return glob.match(sectionName);
235+
});
236+
if (!isMatch)
237+
continue;
238+
sectionNameToIdxsForCompression[sectionName].push_back(sectionIdx);
237239
}
238240

239241
if (compressionSortStartupFunctions) {
@@ -252,51 +254,43 @@ auto BPOrderer<D>::computeOrder(
252254
}
253255
}
254256

255-
// Map a section index (order directly) to a list of duplicate section indices
256-
// (not ordered directly).
257+
// Map a section index (ordered directly) to a list of duplicate section
258+
// indices (not ordered directly).
257259
DenseMap<unsigned, SmallVector<unsigned, 0>> duplicateSectionIdxs;
258-
auto unsForFunctionCompression = getUnsForCompression<D>(
259-
sections, sectionToIdx, sectionIdxsForFunctionCompression,
260-
&duplicateSectionIdxs, maxUN);
261-
auto unsForDataCompression = getUnsForCompression<D>(
262-
sections, sectionToIdx, sectionIdxsForDataCompression,
263-
&duplicateSectionIdxs, maxUN);
264-
265-
std::vector<BPFunctionNode> nodesForStartup, nodesForFunctionCompression,
266-
nodesForDataCompression;
260+
SmallVector<std::vector<BPFunctionNode>> nodesForCompression;
261+
for (auto &[name, idxs] : sectionNameToIdxsForCompression) {
262+
auto &nodes = nodesForCompression.emplace_back();
263+
auto uns = getUnsForCompression<D>(sections, sectionToIdx, idxs,
264+
&duplicateSectionIdxs, maxUN);
265+
for (auto &[sectionIdx, uns] : uns)
266+
nodes.emplace_back(sectionIdx, uns);
267+
// Sort compression nodes by their Id (which is the section index) because
268+
// the input linker order tends to be not bad.
269+
llvm::sort(nodes, [](auto &L, auto &R) { return L.Id < R.Id; });
270+
}
271+
272+
std::vector<BPFunctionNode> nodesForStartup;
267273
for (auto &[sectionIdx, uns] : startupSectionIdxUNs)
268274
nodesForStartup.emplace_back(sectionIdx, uns);
269-
for (auto &[sectionIdx, uns] : unsForFunctionCompression)
270-
nodesForFunctionCompression.emplace_back(sectionIdx, uns);
271-
for (auto &[sectionIdx, uns] : unsForDataCompression)
272-
nodesForDataCompression.emplace_back(sectionIdx, uns);
273275

274276
// Use the first timestamp to define the initial order for startup nodes.
275277
llvm::sort(nodesForStartup, [&sectionIdxToTimestamp](auto &L, auto &R) {
276278
return std::make_pair(sectionIdxToTimestamp[L.Id], L.Id) <
277279
std::make_pair(sectionIdxToTimestamp[R.Id], R.Id);
278280
});
279-
// Sort compression nodes by their Id (which is the section index) because the
280-
// input linker order tends to be not bad.
281-
llvm::sort(nodesForFunctionCompression,
282-
[](auto &L, auto &R) { return L.Id < R.Id; });
283-
llvm::sort(nodesForDataCompression,
284-
[](auto &L, auto &R) { return L.Id < R.Id; });
285281

286282
{
287283
TimeTraceScope timeScope("Balanced Partitioning");
288284
BalancedPartitioningConfig config;
289285
BalancedPartitioning bp(config);
290286
bp.run(nodesForStartup);
291-
bp.run(nodesForFunctionCompression);
292-
bp.run(nodesForDataCompression);
287+
for (auto &nodes : nodesForCompression)
288+
bp.run(nodes);
293289
}
294290

295291
unsigned numStartupSections = 0, startupSize = 0;
296-
unsigned numCodeCompressionSections = 0, codeCompressionSize = 0;
297-
unsigned numDuplicateCodeSections = 0, duplicateCodeSize = 0;
298-
unsigned numDataCompressionSections = 0, dataCompressionSize = 0;
299-
unsigned numDuplicateDataSections = 0, duplicateDataSize = 0;
292+
unsigned numCompressionSections = 0, compressionSize = 0;
293+
unsigned numDuplicateCompressionSections = 0, duplicateCompressionSize = 0;
300294
SetVector<const Section *> orderedSections;
301295
// Order startup functions,
302296
for (auto &node : nodesForStartup) {
@@ -306,63 +300,49 @@ auto BPOrderer<D>::computeOrder(
306300
++numStartupSections;
307301
}
308302
}
309-
// then functions for compression,
310-
for (auto &node : nodesForFunctionCompression) {
311-
const auto *isec = sections[node.Id];
312-
if (orderedSections.insert(isec)) {
313-
codeCompressionSize += D::getSize(*isec);
314-
++numCodeCompressionSections;
315-
}
316-
auto It = duplicateSectionIdxs.find(node.Id);
317-
if (It == duplicateSectionIdxs.end())
318-
continue;
319-
for (auto dupSecIdx : It->getSecond()) {
320-
const auto *dupIsec = sections[dupSecIdx];
321-
if (orderedSections.insert(dupIsec)) {
322-
duplicateCodeSize += D::getSize(*dupIsec);
323-
++numDuplicateCodeSections;
303+
// then sections for compression.
304+
for (const auto &nodes : nodesForCompression) {
305+
for (auto &node : nodes) {
306+
const auto *isec = sections[node.Id];
307+
if (orderedSections.insert(isec)) {
308+
compressionSize += D::getSize(*isec);
309+
++numCompressionSections;
324310
}
325-
}
326-
}
327-
// then data for compression.
328-
for (auto &node : nodesForDataCompression) {
329-
const auto *isec = sections[node.Id];
330-
if (orderedSections.insert(isec)) {
331-
dataCompressionSize += D::getSize(*isec);
332-
++numDataCompressionSections;
333-
}
334-
auto It = duplicateSectionIdxs.find(node.Id);
335-
if (It == duplicateSectionIdxs.end())
336-
continue;
337-
for (auto dupSecIdx : It->getSecond()) {
338-
const auto *dupIsec = sections[dupSecIdx];
339-
if (orderedSections.insert(dupIsec)) {
340-
duplicateDataSize += D::getSize(*dupIsec);
341-
++numDuplicateDataSections;
311+
auto It = duplicateSectionIdxs.find(node.Id);
312+
if (It == duplicateSectionIdxs.end())
313+
continue;
314+
for (auto dupSecIdx : It->getSecond()) {
315+
const auto *dupIsec = sections[dupSecIdx];
316+
if (orderedSections.insert(dupIsec)) {
317+
duplicateCompressionSize += D::getSize(*dupIsec);
318+
++numDuplicateCompressionSections;
319+
}
342320
}
343321
}
344322
}
345323

346324
if (verbose) {
347-
unsigned numTotalOrderedSections =
348-
numStartupSections + numCodeCompressionSections +
349-
numDuplicateCodeSections + numDataCompressionSections +
350-
numDuplicateDataSections;
351-
unsigned totalOrderedSize = startupSize + codeCompressionSize +
352-
duplicateCodeSize + dataCompressionSize +
353-
duplicateDataSize;
325+
unsigned numTotalOrderedSections = numStartupSections +
326+
numCompressionSections +
327+
numDuplicateCompressionSections;
328+
unsigned totalOrderedSize =
329+
startupSize + compressionSize + duplicateCompressionSize;
330+
SmallVector<StringRef> sectionNames;
331+
for (auto &[name, idxs] : sectionNameToIdxsForCompression)
332+
sectionNames.push_back(name);
333+
llvm::sort(sectionNames);
354334
dbgs() << "Ordered " << numTotalOrderedSections << " sections ("
355335
<< totalOrderedSize << " bytes) using balanced partitioning:\n";
356336
dbgs() << " Functions for startup: " << numStartupSections << " ("
357337
<< startupSize << " bytes)\n";
358-
dbgs() << " Functions for compression: " << numCodeCompressionSections
359-
<< " (" << codeCompressionSize << " bytes)\n";
360-
dbgs() << " Duplicate functions: " << numDuplicateCodeSections << " ("
361-
<< duplicateCodeSize << " bytes)\n";
362-
dbgs() << " Data for compression: " << numDataCompressionSections << " ("
363-
<< dataCompressionSize << " bytes)\n";
364-
dbgs() << " Duplicate data: " << numDuplicateDataSections << " ("
365-
<< duplicateDataSize << " bytes)\n";
338+
dbgs() << " Sections for compression: " << numCompressionSections << " ("
339+
<< compressionSize << " bytes)\n ";
340+
for (StringRef name : sectionNames)
341+
dbgs() << name << " ";
342+
dbgs() << "\n";
343+
dbgs() << " Duplicate compression sections: "
344+
<< numDuplicateCompressionSections << " ("
345+
<< duplicateCompressionSize << " bytes)\n";
366346

367347
if (!profilePath.empty()) {
368348
// Evaluate this function order for startup

0 commit comments

Comments
 (0)