Skip to content

Commit bcc1e58

Browse files
committed
[ELF] Allow --symbol-ordering-file and call graph profile to be used together
Port https://reviews.llvm.org/D117354 from the MachO port. If both --symbol-ordering-file and call graph profile are present, the --symbol-ordering-file takes precedence, but the call graph profile is still used for symbols that don't appear in the order file. In addition, call graph profile described sections are now ordered before other sections.
1 parent 8d2b070 commit bcc1e58

File tree

4 files changed

+53
-14
lines changed

4 files changed

+53
-14
lines changed

lld/ELF/CallGraphSort.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ DenseMap<const InputSectionBase *, int> CallGraphSort::run() {
235235
});
236236

237237
DenseMap<const InputSectionBase *, int> orderMap;
238-
int curOrder = 1;
238+
int curOrder = -clusters.size();
239239
for (int leader : sorted) {
240240
for (int i = leader;;) {
241241
orderMap[sections[i]] = curOrder++;
@@ -328,7 +328,7 @@ computeCacheDirectedSortOrder(Ctx &ctx) {
328328

329329
// Create the final order.
330330
DenseMap<const InputSectionBase *, int> orderMap;
331-
int curOrder = 1;
331+
int curOrder = -sortedSections.size();
332332
for (uint64_t secIdx : sortedSections)
333333
orderMap[sections[secIdx]] = curOrder++;
334334

lld/ELF/Driver.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,13 +1746,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
17461746
if (args.hasArg(OPT_call_graph_ordering_file))
17471747
ErrAlways(ctx) << "--symbol-ordering-file and --call-graph-order-file "
17481748
"may not be used together";
1749-
if (std::optional<MemoryBufferRef> buffer =
1750-
readFile(ctx, arg->getValue())) {
1749+
if (auto buffer = readFile(ctx, arg->getValue()))
17511750
ctx.arg.symbolOrderingFile = getSymbolOrderingFile(ctx, *buffer);
1752-
// Also need to disable CallGraphProfileSort to prevent
1753-
// LLD order symbols with CGProfile
1754-
ctx.arg.callGraphProfileSort = CGProfileSortKind::None;
1755-
}
17561751
}
17571752

17581753
assert(ctx.arg.versionDefinitions.empty());

lld/ELF/Writer.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,11 +1080,14 @@ static void maybeShuffle(Ctx &ctx,
10801080
}
10811081
}
10821082

1083-
// Builds section order for handling --symbol-ordering-file.
1083+
// Return section order within an InputSectionDescription.
1084+
// If both --symbol-ordering-file and call graph profile are present, the order
1085+
// file takes precedence, but the call graph profile is still used for symbols
1086+
// that don't appear in the order file.
10841087
static DenseMap<const InputSectionBase *, int> buildSectionOrder(Ctx &ctx) {
10851088
DenseMap<const InputSectionBase *, int> sectionOrder;
10861089
if (!ctx.arg.callGraphProfile.empty())
1087-
return computeCallGraphProfileOrder(ctx);
1090+
sectionOrder = computeCallGraphProfileOrder(ctx);
10881091

10891092
if (ctx.arg.symbolOrderingFile.empty())
10901093
return sectionOrder;
@@ -1098,7 +1101,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder(Ctx &ctx) {
10981101
// appear in the symbol ordering file have the lowest priority 0.
10991102
// All explicitly mentioned symbols have negative (higher) priorities.
11001103
DenseMap<CachedHashStringRef, SymbolOrderEntry> symbolOrder;
1101-
int priority = -ctx.arg.symbolOrderingFile.size();
1104+
int priority = -sectionOrder.size() - ctx.arg.symbolOrderingFile.size();
11021105
for (StringRef s : ctx.arg.symbolOrderingFile)
11031106
symbolOrder.insert({CachedHashStringRef(s), {priority++, false}});
11041107

@@ -1254,11 +1257,11 @@ static void sortSection(Ctx &ctx, OutputSection &osec,
12541257
}
12551258
}
12561259

1257-
// If no layout was provided by linker script, we want to apply default
1258-
// sorting for special input sections. This also handles --symbol-ordering-file.
1260+
// Sort sections within each InputSectionDescription.
12591261
template <class ELFT> void Writer<ELFT>::sortInputSections() {
1260-
// Build the order once since it is expensive.
1262+
// Assign negative priorities.
12611263
DenseMap<const InputSectionBase *, int> order = buildSectionOrder(ctx);
1264+
// Assign non-negative priorities due to --shuffle-sections.
12621265
maybeShuffle(ctx, order);
12631266
for (SectionCommand *cmd : ctx.script->sectionCommands)
12641267
if (auto *osd = dyn_cast<OutputDesc>(cmd))

lld/test/ELF/cgprofile-orderfile.s

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# REQUIRES: x86
2+
3+
# RUN: rm -rf %t && split-file %s %t && cd %t
4+
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
5+
6+
# RUN: ld.lld -e A a.o --symbol-ordering-file=order --call-graph-profile-sort=hfsort -o out
7+
# RUN: llvm-nm --numeric-sort out | FileCheck %s
8+
# RUN: ld.lld -e A a.o --call-graph-profile-sort=hfsort -o out1
9+
# RUN: llvm-nm --numeric-sort out1 | FileCheck %s --check-prefix=ONLY-CG
10+
11+
#--- order
12+
B
13+
A
14+
15+
#--- a.s
16+
.section .text.D,"ax"; .globl D; D:
17+
retq
18+
19+
.section .text.C,"ax"; .globl C; C:
20+
call D
21+
22+
.section .text.B,"ax"; .globl B; B:
23+
retq
24+
25+
.section .text.A,"ax"; .globl A; A:
26+
call B
27+
call C
28+
29+
.cg_profile A, B, 100
30+
.cg_profile A, C, 40
31+
.cg_profile C, D, 61
32+
33+
# CHECK: T B
34+
# CHECK-NEXT: T A
35+
# CHECK-NEXT: T C
36+
# CHECK-NEXT: T D
37+
38+
# ONLY-CG: T A
39+
# ONLY-CG-NEXT: T B
40+
# ONLY-CG-NEXT: T C
41+
# ONLY-CG-NEXT: T D

0 commit comments

Comments
 (0)