Skip to content

Commit 37f25a2

Browse files
committedJul 21, 2018
ELF: Make sections with KeepUnique bit eligible for ICF.
The only restriction is that we cannot merge more than one KeepUnique section together. This matches gold's behaviour and reduces code size when using --icf=safe. Differential Revision: https://reviews.llvm.org/D49622 llvm-svn: 337638
1 parent 960246d commit 37f25a2

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed
 

‎lld/ELF/ICF.cpp

+23-4
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ template <class ELFT> static uint32_t getHash(InputSection *S) {
163163

164164
// Returns true if section S is subject of ICF.
165165
static bool isEligible(InputSection *S) {
166-
if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC))
166+
if (!S->Live || !(S->Flags & SHF_ALLOC))
167167
return false;
168168

169169
// Don't merge writable sections. .data.rel.ro sections are marked as writable
@@ -468,10 +468,29 @@ template <class ELFT> void ICF<ELFT>::run() {
468468
forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) {
469469
if (End - Begin == 1)
470470
return;
471-
print("selected section " + toString(Sections[Begin]));
472-
for (size_t I = Begin + 1; I < End; ++I) {
471+
InputSection *Target = nullptr;
472+
bool SeenUnique = false, Replaced = false;
473+
for (size_t I = Begin; I < End; ++I) {
474+
// We aren't allowed to merge two KeepUnique sections as this would break
475+
// the guarantees provided by --keep-unique and --icf=safe, but there's
476+
// no reason why we can't merge a non-KeepUnique section with a KeepUnique
477+
// section. We implement this by only considering the first KeepUnique
478+
// section in the equivalence class for merging. If we see any more
479+
// KeepUnique sections, we ignore them.
480+
if (Sections[I]->KeepUnique) {
481+
if (SeenUnique)
482+
continue;
483+
SeenUnique = true;
484+
}
485+
if (!Target) {
486+
Target = Sections[I];
487+
continue;
488+
}
489+
if (!Replaced)
490+
print("selected section " + toString(Target));
473491
print(" removing identical section " + toString(Sections[I]));
474-
Sections[Begin]->replace(Sections[I]);
492+
Target->replace(Sections[I]);
493+
Replaced = true;
475494

476495
// At this point we know sections merged are fully identical and hence
477496
// we want to remove duplicate implicit dependencies such as link order

‎lld/test/ELF/icf-keep-unique.s

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
// CHECK-NEXT: removing identical section {{.*}}:(.text.f4)
1212
// CHECK-NEXT: removing identical section {{.*}}:(.text.f5)
1313

14-
// With --keep-unique f2, f4 and f5 we expect only f3 and f5 to be removed.
14+
// With --keep-unique f2, f4 and f5 we expect only f2, f3 and f5 to be removed.
15+
// f2 can be removed despite being --keep-unique because all sections that are
16+
// merged into it are not --keep-unique.
1517
// f5 is not matched by --keep-unique as it is a local symbol.
1618
// CHECK-KEEP: warning: could not find symbol f5 to keep unique
1719
// CHECK-KEEP: selected section {{.*}}:(.text.f1)
20+
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f2)
1821
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f3)
1922
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f5)
2023
.globl _start, f1, f2, f3, f4

0 commit comments

Comments
 (0)
Please sign in to comment.