[PATCH] D19528: [ELF] - Implemented -z combrelocs/nocombreloc.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Fri May 6 13:35:35 PDT 2016


I was able to manually apply it.

What I did was:

* build clang with shared libraries.
* time with
 sudo schedtool -F -p 99 -a 0x4 -e perf stat -r 10 ./bin/clang
* build the patched version of lld
* delete bin/clang-3.9 and lib/*.so
* link again
* time the result

What I got was

* trunk: 0.059005660
* sort on RELATIVE, Symbol, offset, type: 0.040090757
* sort on Symbol, offset, type: 0.042367124
* sort on offset, type: 0.059119353
* sort on RELATIVE, Symbol, offset: 0.040131764
* sort on RELATIVE, Symbol: 0.040396584
* sort on RELATIVE: 0.058322444
* sort on Symbol: 0.039886032

So it looks like the only thing that makes a difference is the symbol.

BTW, one cannot sort .rel.plt, it would be nice to document why.
I think it is better to use stable_sort to be sure we have a
deterministic output without checking fields that don't make a
difference.

So a change sorting only by symbol with stable sort LGTM. Please make
sure you are not computing the number of relative rolocations or
setting any DT_*.

The partial apply that I used for benchmarking was.

Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 9a44339..dffcb9b 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -301,9 +301,9 @@ template <class ELFT> void PltSection<ELFT>::finalize() {
 }
 
 template <class ELFT>
-RelocationSection<ELFT>::RelocationSection(StringRef Name)
+RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)
     : OutputSectionBase<ELFT>(Name, Config->Rela ? SHT_RELA : SHT_REL,
-                              SHF_ALLOC) {
+                              SHF_ALLOC), Sort(Sort) {
   this->Header.sh_entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   this->Header.sh_addralign = sizeof(uintX_t);
 }
@@ -313,7 +313,21 @@ void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) {
   Relocs.push_back(Reloc);
 }
 
+template <class ELFT, class RelTy>
+static bool compRelocations(const RelTy &A, const RelTy &B) {
+  uint8_t AType = A.getType(Config->Mips64EL);
+  uint8_t BType = B.getType(Config->Mips64EL);
+
+  uint32_t I = A.getSymbol(Config->Mips64EL);
+  uint32_t J = B.getSymbol(Config->Mips64EL);
+  if (I != J)
+    return I < J;
+
+  return false;
+}
+
 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
+  uint8_t *BufBegin = Buf;
   for (const DynamicReloc<ELFT> &Rel : Relocs) {
     auto *P = reinterpret_cast<Elf_Rela *>(Buf);
     Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
@@ -325,6 +339,15 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
     uint32_t SymIdx = (!Rel.UseSymVA && Sym) ? Sym->DynsymIndex : 0;
     P->setSymbolAndType(SymIdx, Rel.Type, Config->Mips64EL);
   }
+
+  if (!Sort)
+    return;
+  if (Config->Rela)
+    std::stable_sort((Elf_Rela *)BufBegin, (Elf_Rela *)BufBegin + Relocs.size(),
+              compRelocations<ELFT, Elf_Rela>);
+  else
+    std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(),
+              compRelocations<ELFT, Elf_Rel>);
 }
 
 template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index d8c0e5b..b94f765 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -274,7 +274,7 @@ class RelocationSection final : public OutputSectionBase<ELFT> {
   typedef typename ELFT::uint uintX_t;
 
 public:
-  RelocationSection(StringRef Name);
+  RelocationSection(StringRef Name, bool Sort);
   void addReloc(const DynamicReloc<ELFT> &Reloc);
   unsigned getRelocOffset();
   void finalize() override;
@@ -284,6 +284,7 @@ public:
   bool Static = false;
 
 private:
+  bool Sort;
   std::vector<DynamicReloc<ELFT>> Relocs;
 };
 
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 8d92229..8fdaebf 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -129,7 +129,8 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
   GotSection<ELFT> Got;
   InterpSection<ELFT> Interp;
   PltSection<ELFT> Plt;
-  RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn");
+  RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn",
+                                  true);
   StringTableSection<ELFT> DynStrTab(".dynstr", true);
   StringTableSection<ELFT> ShStrTab(".shstrtab", false);
   SymbolTableSection<ELFT> DynSymTab(*Symtab, DynStrTab);
@@ -165,7 +166,7 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
   if (Target->UseLazyBinding) {
     StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt";
     GotPlt.reset(new GotPltSection<ELFT>);
-    RelaPlt.reset(new RelocationSection<ELFT>(S));
+    RelaPlt.reset(new RelocationSection<ELFT>(S, false));
   }
   if (!Config->StripAll) {
     StrTab.reset(new StringTableSection<ELFT>(".strtab", false));


More information about the llvm-commits mailing list