[lld] r337638 - ELF: Make sections with KeepUnique bit eligible for ICF.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 20 17:17:11 PDT 2018


Author: pcc
Date: Fri Jul 20 17:17:11 2018
New Revision: 337638

URL: http://llvm.org/viewvc/llvm-project?rev=337638&view=rev
Log:
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

Modified:
    lld/trunk/ELF/ICF.cpp
    lld/trunk/test/ELF/icf-keep-unique.s

Modified: lld/trunk/ELF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=337638&r1=337637&r2=337638&view=diff
==============================================================================
--- lld/trunk/ELF/ICF.cpp (original)
+++ lld/trunk/ELF/ICF.cpp Fri Jul 20 17:17:11 2018
@@ -163,7 +163,7 @@ template <class ELFT> static uint32_t ge
 
 // 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>::ru
   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

Modified: lld/trunk/test/ELF/icf-keep-unique.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/icf-keep-unique.s?rev=337638&r1=337637&r2=337638&view=diff
==============================================================================
--- lld/trunk/test/ELF/icf-keep-unique.s (original)
+++ lld/trunk/test/ELF/icf-keep-unique.s Fri Jul 20 17:17:11 2018
@@ -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




More information about the llvm-commits mailing list