summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2018-07-21 00:17:11 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2018-07-21 00:17:11 +0000
commit37f25a24bbf1fdb384c1e2559f033952f934a6e1 (patch)
treee3d3524213f8ff3a4de5ca0d2532b3f6001f66fa
parent960246dbee67c827eb4339b0fe68b7534b5a79d8 (diff)
downloadbcm5719-llvm-37f25a24bbf1fdb384c1e2559f033952f934a6e1.tar.gz
bcm5719-llvm-37f25a24bbf1fdb384c1e2559f033952f934a6e1.zip
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
-rw-r--r--lld/ELF/ICF.cpp27
-rw-r--r--lld/test/ELF/icf-keep-unique.s5
2 files changed, 27 insertions, 5 deletions
diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index f13a5049e01..191fa8e2b6e 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -163,7 +163,7 @@ template <class ELFT> static uint32_t getHash(InputSection *S) {
// Returns true if section S is subject of ICF.
static bool isEligible(InputSection *S) {
- if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC))
+ if (!S->Live || !(S->Flags & SHF_ALLOC))
return false;
// Don't merge writable sections. .data.rel.ro sections are marked as writable
@@ -468,10 +468,29 @@ template <class ELFT> void ICF<ELFT>::run() {
forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) {
if (End - Begin == 1)
return;
- print("selected section " + toString(Sections[Begin]));
- for (size_t I = Begin + 1; I < End; ++I) {
+ InputSection *Target = nullptr;
+ bool SeenUnique = false, Replaced = false;
+ for (size_t I = Begin; I < End; ++I) {
+ // We aren't allowed to merge two KeepUnique sections as this would break
+ // the guarantees provided by --keep-unique and --icf=safe, but there's
+ // no reason why we can't merge a non-KeepUnique section with a KeepUnique
+ // section. We implement this by only considering the first KeepUnique
+ // section in the equivalence class for merging. If we see any more
+ // KeepUnique sections, we ignore them.
+ if (Sections[I]->KeepUnique) {
+ if (SeenUnique)
+ continue;
+ SeenUnique = true;
+ }
+ if (!Target) {
+ Target = Sections[I];
+ continue;
+ }
+ if (!Replaced)
+ print("selected section " + toString(Target));
print(" removing identical section " + toString(Sections[I]));
- Sections[Begin]->replace(Sections[I]);
+ Target->replace(Sections[I]);
+ Replaced = true;
// At this point we know sections merged are fully identical and hence
// we want to remove duplicate implicit dependencies such as link order
diff --git a/lld/test/ELF/icf-keep-unique.s b/lld/test/ELF/icf-keep-unique.s
index a6f883fc7b2..661d0e285f6 100644
--- a/lld/test/ELF/icf-keep-unique.s
+++ b/lld/test/ELF/icf-keep-unique.s
@@ -11,10 +11,13 @@
// CHECK-NEXT: removing identical section {{.*}}:(.text.f4)
// CHECK-NEXT: removing identical section {{.*}}:(.text.f5)
-// With --keep-unique f2, f4 and f5 we expect only f3 and f5 to be removed.
+// With --keep-unique f2, f4 and f5 we expect only f2, f3 and f5 to be removed.
+// f2 can be removed despite being --keep-unique because all sections that are
+// merged into it are not --keep-unique.
// f5 is not matched by --keep-unique as it is a local symbol.
// CHECK-KEEP: warning: could not find symbol f5 to keep unique
// CHECK-KEEP: selected section {{.*}}:(.text.f1)
+// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f2)
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f3)
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f5)
.globl _start, f1, f2, f3, f4
OpenPOWER on IntegriCloud