Skip to content

Commit dac737e

Browse files
ColibrowMaskRay
authored andcommitted
rewrite BPSectionOrder in ELF following llvm#124482
1 parent dad8b8b commit dac737e

File tree

2 files changed

+88
-116
lines changed

2 files changed

+88
-116
lines changed

lld/ELF/BPSectionOrderer.cpp

Lines changed: 83 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===- BPSectionOrderer.cpp------------------------------------------------===//
1+
//===- BPSectionOrderer.cpp -----------------------------------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,45 +7,98 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "BPSectionOrderer.h"
10+
#include "InputFiles.h"
11+
#include "InputSection.h"
12+
#include "SymbolTable.h"
13+
#include "Symbols.h"
14+
#include "lld/Common/BPSectionOrdererBase.inc"
15+
#include "llvm/Support/Endian.h"
16+
17+
#define DEBUG_TYPE "bp-section-orderer"
1018

1119
using namespace llvm;
1220
using namespace lld::elf;
1321

14-
void BPSectionELF::getSectionHashes(
15-
llvm::SmallVectorImpl<uint64_t> &hashes,
16-
const llvm::DenseMap<const void *, uint64_t> &sectionToIdx) const {
17-
constexpr unsigned windowSize = 4;
22+
namespace {
23+
struct BPOrdererELF;
24+
}
25+
template <> struct lld::BPOrdererTraits<struct BPOrdererELF> {
26+
using Section = elf::InputSectionBase;
27+
using Symbol = elf::Symbol;
28+
};
29+
namespace {
30+
struct BPOrdererELF : lld::BPOrderer<BPOrdererELF> {
31+
static uint64_t getSize(const Section &sec) { return sec.getSize(); }
32+
static bool isCodeSection(const Section &sec) {
33+
return sec.flags & llvm::ELF::SHF_EXECINSTR;
34+
}
35+
static SmallVector<Symbol *, 0> getSymbols(const Section &sec) {
36+
SmallVector<Symbol *, 0> symbols;
37+
for (auto *sym : sec.file->getSymbols())
38+
if (auto *d = llvm::dyn_cast_or_null<Defined>(sym))
39+
if (d->size > 0 && d->section == &sec)
40+
symbols.emplace_back(d);
41+
return symbols;
42+
}
43+
44+
std::optional<StringRef> static getResolvedLinkageName(llvm::StringRef name) {
45+
return name;
46+
}
47+
48+
static void
49+
getSectionHashes(const Section &sec, llvm::SmallVectorImpl<uint64_t> &hashes,
50+
const llvm::DenseMap<const void *, uint64_t> &sectionToIdx) {
51+
constexpr unsigned windowSize = 4;
1852

19-
// Calculate content hashes: k-mers and the last k-1 bytes.
20-
ArrayRef<uint8_t> data = isec->content();
21-
if (data.size() >= windowSize)
22-
for (size_t i = 0; i <= data.size() - windowSize; ++i)
23-
hashes.push_back(llvm::support::endian::read32le(data.data() + i));
24-
for (uint8_t byte : data.take_back(windowSize - 1))
25-
hashes.push_back(byte);
53+
// Calculate content hashes: k-mers and the last k-1 bytes.
54+
ArrayRef<uint8_t> data = sec.content();
55+
if (data.size() >= windowSize)
56+
for (size_t i = 0; i <= data.size() - windowSize; ++i)
57+
hashes.push_back(llvm::support::endian::read32le(data.data() + i));
58+
for (uint8_t byte : data.take_back(windowSize - 1))
59+
hashes.push_back(byte);
2660

27-
llvm::sort(hashes);
28-
hashes.erase(std::unique(hashes.begin(), hashes.end()), hashes.end());
29-
}
61+
llvm::sort(hashes);
62+
hashes.erase(std::unique(hashes.begin(), hashes.end()), hashes.end());
63+
}
64+
65+
static llvm::StringRef getSymName(const Symbol &sym) { return sym.getName(); }
66+
static uint64_t getSymValue(const Symbol &sym) {
67+
if (auto *d = dyn_cast<Defined>(&sym))
68+
return d->value;
69+
return 0;
70+
}
71+
static uint64_t getSymSize(const Symbol &sym) {
72+
if (auto *d = dyn_cast<Defined>(&sym))
73+
return d->size;
74+
return 0;
75+
}
76+
};
77+
} // namespace
3078

31-
llvm::DenseMap<const lld::elf::InputSectionBase *, int>
32-
lld::elf::runBalancedPartitioning(Ctx &ctx, llvm::StringRef profilePath,
33-
bool forFunctionCompression,
34-
bool forDataCompression,
35-
bool compressionSortStartupFunctions,
36-
bool verbose) {
37-
// Collect sections from symbols and wrap as BPSectionELF instances.
38-
// Deduplicates sections referenced by multiple symbols.
39-
SmallVector<std::unique_ptr<BPSectionBase>> sections;
79+
DenseMap<const InputSectionBase *, int> lld::elf::runBalancedPartitioning(
80+
Ctx &ctx, StringRef profilePath, bool forFunctionCompression,
81+
bool forDataCompression, bool compressionSortStartupFunctions,
82+
bool verbose) {
83+
// Collect candidate sections and associated symbols.
84+
SmallVector<InputSectionBase *> sections;
85+
DenseMap<CachedHashStringRef, DenseSet<unsigned>> rootSymbolToSectionIdxs;
4086
DenseSet<const InputSectionBase *> seenSections;
4187

4288
auto addSection = [&](Symbol &sym) {
4389
if (sym.getSize() == 0)
4490
return;
4591
if (auto *d = dyn_cast<Defined>(&sym))
4692
if (auto *sec = dyn_cast_or_null<InputSectionBase>(d->section))
47-
if (seenSections.insert(sec).second)
48-
sections.emplace_back(std::make_unique<BPSectionELF>(sec));
93+
if (seenSections.insert(sec).second) {
94+
size_t idx = sections.size();
95+
sections.emplace_back(sec);
96+
auto rootName = getRootSymbol(sym.getName());
97+
rootSymbolToSectionIdxs[CachedHashStringRef(rootName)].insert(idx);
98+
if (auto linkageName = BPOrdererELF::getResolvedLinkageName(rootName))
99+
rootSymbolToSectionIdxs[CachedHashStringRef(*linkageName)].insert(
100+
idx);
101+
}
49102
};
50103

51104
for (Symbol *sym : ctx.symtab->getSymbols())
@@ -55,16 +108,8 @@ lld::elf::runBalancedPartitioning(Ctx &ctx, llvm::StringRef profilePath,
55108
for (Symbol *sym : file->getLocalSymbols())
56109
addSection(*sym);
57110

58-
auto reorderedSections = BPSectionBase::reorderSectionsByBalancedPartitioning(
59-
profilePath, forFunctionCompression, forDataCompression,
60-
compressionSortStartupFunctions, verbose, sections);
61-
62-
DenseMap<const InputSectionBase *, int> result;
63-
for (const auto [sec, priority] : reorderedSections) {
64-
auto *elfSection = cast<BPSectionELF>(sec);
65-
result.try_emplace(
66-
static_cast<const InputSectionBase *>(elfSection->getSection()),
67-
static_cast<int>(priority));
68-
}
69-
return result;
111+
return BPOrdererELF::computeOrder(profilePath, forFunctionCompression,
112+
forDataCompression,
113+
compressionSortStartupFunctions, verbose,
114+
sections, rootSymbolToSectionIdxs);
70115
}

lld/ELF/BPSectionOrderer.h

Lines changed: 5 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,96 +14,23 @@
1414
#ifndef LLD_ELF_BPSECTION_ORDERER_H
1515
#define LLD_ELF_BPSECTION_ORDERER_H
1616

17-
#include "InputFiles.h"
18-
#include "InputSection.h"
19-
#include "SymbolTable.h"
20-
#include "lld/Common/BPSectionOrdererBase.h"
2117
#include "llvm/ADT/DenseMap.h"
22-
#include "llvm/ADT/STLExtras.h"
2318
#include "llvm/ADT/StringRef.h"
24-
#include "llvm/BinaryFormat/ELF.h"
2519

2620
namespace lld::elf {
27-
28-
class InputSection;
29-
30-
class BPSymbolELF : public BPSymbol {
31-
const Symbol *sym;
32-
33-
public:
34-
explicit BPSymbolELF(const Symbol *s) : sym(s) {}
35-
36-
llvm::StringRef getName() const override { return sym->getName(); }
37-
38-
const Defined *asDefined() const { return llvm::dyn_cast<Defined>(sym); }
39-
40-
std::optional<uint64_t> getValue() const override {
41-
if (auto *d = asDefined())
42-
return d->value;
43-
return {};
44-
}
45-
46-
std::optional<uint64_t> getSize() const override {
47-
if (auto *d = asDefined())
48-
return d->size;
49-
return {};
50-
}
51-
52-
InputSectionBase *getInputSection() const {
53-
if (auto *d = asDefined())
54-
return llvm::dyn_cast_or_null<InputSectionBase>(d->section);
55-
return nullptr;
56-
}
57-
58-
const Symbol *getSymbol() const { return sym; }
59-
};
60-
61-
class BPSectionELF : public BPSectionBase {
62-
const InputSectionBase *isec;
63-
64-
public:
65-
explicit BPSectionELF(const InputSectionBase *sec) : isec(sec) {}
66-
67-
const void *getSection() const override { return isec; }
68-
69-
uint64_t getSize() const override { return isec->getSize(); }
70-
71-
bool isCodeSection() const override {
72-
return isec->flags & llvm::ELF::SHF_EXECINSTR;
73-
}
74-
75-
SmallVector<std::unique_ptr<BPSymbol>> getSymbols() const override {
76-
SmallVector<std::unique_ptr<BPSymbol>> symbols;
77-
for (Symbol *sym : isec->file->getSymbols())
78-
if (auto *d = dyn_cast<Defined>(sym))
79-
if (d->size > 0 && d->section == isec)
80-
symbols.emplace_back(std::make_unique<BPSymbolELF>(sym));
81-
82-
return symbols;
83-
}
84-
85-
std::optional<StringRef>
86-
getResolvedLinkageName(llvm::StringRef name) const override {
87-
return {};
88-
}
89-
90-
void getSectionHashes(llvm::SmallVectorImpl<uint64_t> &hashes,
91-
const llvm::DenseMap<const void *, uint64_t>
92-
&sectionToIdx) const override;
93-
94-
static bool classof(const BPSectionBase *s) { return true; }
95-
};
21+
struct Ctx;
22+
class InputSectionBase;
9623

9724
/// Run Balanced Partitioning to find the optimal function and data order to
9825
/// improve startup time and compressed size.
9926
///
100-
/// It is important that -ffunction-sections and -fdata-sections are used to
101-
/// ensure functions and data are in their own sections and thus can be
102-
/// reordered.
27+
/// It is important that .subsections_via_symbols is used to ensure functions
28+
/// and data are in their own sections and thus can be reordered.
10329
llvm::DenseMap<const InputSectionBase *, int>
10430
runBalancedPartitioning(Ctx &ctx, llvm::StringRef profilePath,
10531
bool forFunctionCompression, bool forDataCompression,
10632
bool compressionSortStartupFunctions, bool verbose);
33+
10734
} // namespace lld::elf
10835

10936
#endif

0 commit comments

Comments
 (0)