[lld] r264730 - [ELF][MIPS] Reduce number of redundant entries in the local part of MIPS GOT

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 29 07:07:23 PDT 2016


Author: atanasyan
Date: Tue Mar 29 09:07:22 2016
New Revision: 264730

URL: http://llvm.org/viewvc/llvm-project?rev=264730&view=rev
Log:
[ELF][MIPS] Reduce number of redundant entries in the local part of MIPS GOT

Local symbol which requires GOT entry initialized by "page" address.
This address is high 16 bits of sum of the symbol value and the relocation
addend. In the relocation scanning phase final values of symbols are unknown
so to reduce number of allocated GOT entries do the following trick. Save
all output sections referenced by GOT relocations during the relocation
scanning phase. Then later in the `GotSection::finalize` method calculate
number of "pages" required to cover all saved output sections and allocate
appropriate number of GOT entries. We assume the worst case - each 64kb
page of the output section has at least one GOT relocation against it.

Differential Revision: http://reviews.llvm.org/D18349

Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/test/ELF/mips-got-redundant.s

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=264730&r1=264729&r2=264730&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Mar 29 09:07:22 2016
@@ -115,16 +115,30 @@ template <class ELFT> void GotSection<EL
     //
     // See "Global Offset Table" in Chapter 5:
     // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-    //
-    // FIXME (simon): Now LLD allocates GOT entries for each
-    // "local symbol+addend" pair. That should be fixed to reduce size
-    // of generated GOT.
-    if (Sym.isPreemptible())
-      Sym.MustBeInDynSym = true;
-    else {
+    if (Sym.isLocal()) {
+      // At this point we do not know final symbol value so to reduce number
+      // of allocated GOT entries do the following trick. Save all output
+      // sections referenced by GOT relocations. Then later in the `finalize`
+      // method calculate number of "pages" required to cover all saved output
+      // section and allocate appropriate number of GOT entries.
+      auto *OutSec = cast<DefinedRegular<ELFT>>(&Sym)->Section->OutSec;
+      MipsOutSections.insert(OutSec);
+      return;
+    }
+    if (!Sym.isPreemptible()) {
+      // In case of non-local symbols require an entry in the local part
+      // of MIPS GOT, we set GotIndex to 1 just to accent that this symbol
+      // has the GOT entry and escape creation more redundant GOT entries.
+      // FIXME (simon): We can try to store such symbols in the `Entries`
+      // container. But in that case we have to sort out that container
+      // and update GotIndex assigned to symbols.
+      Sym.GotIndex = 1;
       ++MipsLocalEntries;
       return;
     }
+    // All preemptible symbols with MIPS GOT entries should be represented
+    // in the dynamic symbols table.
+    Sym.MustBeInDynSym = true;
   }
   Sym.GotIndex = Entries.size();
   Entries.push_back(&Sym);
@@ -191,6 +205,14 @@ unsigned GotSection<ELFT>::getMipsLocalE
 }
 
 template <class ELFT> void GotSection<ELFT>::finalize() {
+  for (const OutputSectionBase<ELFT> *OutSec : MipsOutSections) {
+    // Calculate an upper bound of MIPS GOT entries required to store page
+    // addresses of local symbols. We assume the worst case - each 64kb
+    // page of the output section has at least one GOT relocation against it.
+    // Add 0x8000 to the section's size because the page address stored
+    // in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
+    MipsLocalEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff;
+  }
   this->Header.sh_size =
       (Target->GotHeaderEntriesNum + MipsLocalEntries + Entries.size()) *
       sizeof(uintX_t);
@@ -1348,8 +1370,12 @@ SymbolTableSection<ELFT>::SymbolTableSec
 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
 static bool sortMipsSymbols(const std::pair<SymbolBody *, unsigned> &L,
                             const std::pair<SymbolBody *, unsigned> &R) {
-  if (!L.first->isInGot() || !R.first->isInGot())
-    return R.first->isInGot();
+  // Sort entries related to non-local preemptible symbols by GOT indexes.
+  // All other entries go to the first part of GOT in arbitrary order.
+  bool LIsInLocalGot = !L.first->isInGot() || !L.first->isPreemptible();
+  bool RIsInLocalGot = !R.first->isInGot() || !R.first->isPreemptible();
+  if (LIsInLocalGot || RIsInLocalGot)
+    return !RIsInLocalGot;
   return L.first->GotIndex < R.first->GotIndex;
 }
 

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=264730&r1=264729&r2=264730&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Mar 29 09:07:22 2016
@@ -13,6 +13,7 @@
 #include "Config.h"
 
 #include "lld/Core/LLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELF.h"
 
@@ -124,6 +125,8 @@ private:
   std::vector<const SymbolBody *> Entries;
   uint32_t TlsIndexOff = -1;
   uint32_t MipsLocalEntries = 0;
+  // Output sections referenced by MIPS GOT relocations.
+  llvm::SmallPtrSet<const OutputSectionBase<ELFT> *, 10> MipsOutSections;
   llvm::DenseMap<uintX_t, size_t> MipsLocalGotPos;
 
   uintX_t getMipsLocalEntryAddr(uintX_t EntryValue);

Modified: lld/trunk/test/ELF/mips-got-redundant.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-got-redundant.s?rev=264730&r1=264729&r2=264730&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-got-redundant.s (original)
+++ lld/trunk/test/ELF/mips-got-redundant.s Tue Mar 29 09:07:22 2016
@@ -25,21 +25,6 @@
 # CHECK-NEXT:     Initial: 0x40008
 #                          ^-- glb1
 # CHECK-NEXT:   }
-# CHECK-NEXT:   Entry {
-# CHECK-NEXT:     Address: 0x20014
-# CHECK-NEXT:     Access: -32732
-# CHECK-NEXT:     Initial: 0x0
-# CHECK-NEXT:   }
-# CHECK-NEXT:   Entry {
-# CHECK-NEXT:     Address: 0x20018
-# CHECK-NEXT:     Access: -32728
-# CHECK-NEXT:     Initial: 0x0
-# CHECK-NEXT:   }
-# CHECK-NEXT:   Entry {
-# CHECK-NEXT:     Address: 0x2001C
-# CHECK-NEXT:     Access: -32724
-# CHECK-NEXT:     Initial: 0x0
-# CHECK-NEXT:   }
 # CHECK-NEXT: ]
 
   .text




More information about the llvm-commits mailing list