[lld] r332332 - [ELF] Implement --keep-unique option

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Tue May 15 01:57:21 PDT 2018


Author: psmith
Date: Tue May 15 01:57:21 2018
New Revision: 332332

URL: http://llvm.org/viewvc/llvm-project?rev=332332&view=rev
Log:
[ELF] Implement --keep-unique option

The --keep-unique <symbol> option is taken from gold. The intention is that
<symbol> will be prevented from being folded by ICF. Although not
specifically mentioned in the documentation <symbol> only matches
global symbols, with a warning if the symbol is not found.

The implementation finds the Section defining <symbol> and removes it from
the set of sections considered for ICF.

Differential Revision: https://reviews.llvm.org/D46755


Added:
    lld/trunk/test/ELF/icf-keep-unique.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/ICF.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/Options.td

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=332332&r1=332331&r2=332332&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue May 15 01:57:21 2018
@@ -1163,6 +1163,18 @@ template <class ELFT> static void demote
   }
 }
 
+// Record sections that define symbols mentioned in --keep-unique <symbol>
+// these sections are inelligible for ICF.
+static void findKeepUniqueSections(opt::InputArgList &Args) {
+  for (auto *Arg : Args.filtered(OPT_keep_unique)) {
+    StringRef Name = Arg->getValue();
+    if (auto *Sym = dyn_cast_or_null<Defined>(Symtab->find(Name)))
+      Sym->Section->KeepUnique = true;
+    else
+      warn("could not find symbol " + Name + " to keep unique");
+  }
+}
+
 // Do actual linking. Note that when this function is called,
 // all linker scripts have already been parsed.
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
@@ -1335,8 +1347,10 @@ template <class ELFT> void LinkerDriver:
   markLive<ELFT>();
   demoteSymbols<ELFT>();
   mergeSections();
-  if (Config->ICF)
+  if (Config->ICF) {
+    findKeepUniqueSections(Args);
     doIcf<ELFT>();
+  }
 
   // Read the callgraph now that we know what was gced or icfed
   if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))

Modified: lld/trunk/ELF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=332332&r1=332331&r2=332332&view=diff
==============================================================================
--- lld/trunk/ELF/ICF.cpp (original)
+++ lld/trunk/ELF/ICF.cpp Tue May 15 01:57:21 2018
@@ -162,7 +162,8 @@ 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->Flags & SHF_ALLOC) || (S->Flags & SHF_WRITE))
+  if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC) ||
+      (S->Flags & SHF_WRITE))
     return false;
 
   // Don't merge read only data sections unless

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=332332&r1=332331&r2=332332&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Tue May 15 01:57:21 2018
@@ -61,6 +61,9 @@ public:
 
   unsigned Bss : 1;
 
+  // Set for sections that should not be folded by ICF.
+  unsigned KeepUnique : 1;
+
   // These corresponds to the fields in Elf_Shdr.
   uint32_t Alignment;
   uint64_t Flags;
@@ -85,8 +88,8 @@ protected:
               uint64_t Entsize, uint64_t Alignment, uint32_t Type,
               uint32_t Info, uint32_t Link)
       : Name(Name), Repl(this), SectionKind(SectionKind), Live(false),
-        Bss(false), Alignment(Alignment), Flags(Flags), Entsize(Entsize),
-        Type(Type), Link(Link), Info(Info) {}
+        Bss(false), KeepUnique(false), Alignment(Alignment), Flags(Flags),
+        Entsize(Entsize), Type(Type), Link(Link), Info(Info) {}
 };
 
 // This corresponds to a section of an input file.

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=332332&r1=332331&r2=332332&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Tue May 15 01:57:21 2018
@@ -192,6 +192,8 @@ defm init: Eq<"init">, HelpText<"Specify
 
 defm just_symbols: Eq<"just-symbols">, HelpText<"Just link symbols">;
 
+defm keep_unique: Eq<"keep-unique">, HelpText<"Do not fold this symbol during ICF">;
+
 defm library: Eq<"library">, HelpText<"Root name of library to use">,
   MetaVarName<"<libName>">;
 

Added: lld/trunk/test/ELF/icf-keep-unique.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/icf-keep-unique.s?rev=332332&view=auto
==============================================================================
--- lld/trunk/test/ELF/icf-keep-unique.s (added)
+++ lld/trunk/test/ELF/icf-keep-unique.s Tue May 15 01:57:21 2018
@@ -0,0 +1,43 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --print-icf-sections | FileCheck %s
+# RUN: ld.lld %t -o %t2 --keep-unique f2 --keep-unique f4 --keep-unique f5 --icf=all --print-icf-sections 2>&1 | FileCheck %s -check-prefix=CHECK-KEEP
+
+// Base case, expect only .text.f1 to be kept
+// CHECK: selected section {{.*}}:(.text.f1)
+// CHECK-NEXT:   removing identical section {{.*}}:(.text.f2)
+// CHECK-NEXT:   removing identical section {{.*}}:(.text.f3)
+// 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.
+// 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.f3)
+// CHECK-KEEP-NEXT:   removing identical section {{.*}}:(.text.f5)
+ .globl _start, f1, f2, f3, f4
+_start:
+ ret
+
+ .section .text.f1, "ax"
+f1:
+ nop
+
+ .section .text.f2, "ax"
+f2:
+ nop
+
+.section .text.f3, "ax"
+f3:
+ nop
+
+.section .text.f4, "ax"
+f4:
+ nop
+
+# f5 is local, not found by --keep-unique f5
+.section .text.f5, "ax"
+f5:
+ nop




More information about the llvm-commits mailing list