[lld] r267917 - Skip scanRelocs for non-alloc sections.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 28 11:42:04 PDT 2016


Author: ruiu
Date: Thu Apr 28 13:42:04 2016
New Revision: 267917

URL: http://llvm.org/viewvc/llvm-project?rev=267917&view=rev
Log:
Skip scanRelocs for non-alloc sections.

Relocations against sections with no SHF_ALLOC bit are R_ABS relocations.
Currently we are creating Relocations vector for them, but that is wasteful.
This patch is to skip vector construction and to directly apply relocations
in place.

This patch seems to be pretty effective for large executables with debug info.
r266158 (Rafael's patch to change the way how we apply relocations) caused a
temporary performance degradation for such executables, but this patch makes
it even faster than before.

Time to link clang with debug info (output size is 1070 MB):

  before r266158: 15.312 seconds (0%)
  r266158:        17.301 seconds (+13.0%)
  Head:           16.484 seconds (+7.7%)
  w/patch:        13.166 seconds (-14.0%)

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

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/relocation-non-alloc.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=267917&r1=267916&r2=267917&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Apr 28 13:42:04 2016
@@ -226,8 +226,50 @@ getSymVA(uint32_t Type, typename ELFT::u
   llvm_unreachable("Invalid expression");
 }
 
+// This function applies relocations to sections without SHF_ALLOC bit.
+// Such sections are never mapped to memory at runtime. Debug sections are
+// an example. Relocations in non-alloc sections are much easier to
+// handle than in allocated sections because it will never need complex
+// treatement such as GOT or PLT (because at runtime no one refers them).
+// So, we handle relocations for non-alloc sections directly in this
+// function as a performance optimization.
+template <class ELFT>
+template <class RelTy>
+void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
+  const unsigned Bits = sizeof(uintX_t) * 8;
+  for (const RelTy &Rel : Rels) {
+    uint8_t *BufLoc = Buf + Rel.r_offset;
+    uintX_t AddrLoc = this->OutSec->getVA() + Rel.r_offset;
+    uint32_t Type = Rel.getType(Config->Mips64EL);
+    SymbolBody &Sym = this->File->getRelocTargetSym(Rel);
+
+    if (Target->getRelExpr(Type, Sym) != R_ABS) {
+      error(this->getSectionName() + " has non-ABS reloc");
+      return;
+    }
+
+    uint64_t SymVA = SignExtend64<Bits>(getSymVA<ELFT>(
+        Type, getAddend<ELFT>(Rel), AddrLoc, Sym, BufLoc, *this->File, R_ABS));
+    Target->relocateOne(BufLoc, Type, SymVA);
+  }
+}
+
 template <class ELFT>
 void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) {
+  // scanReloc function in Writer.cpp constructs Relocations
+  // vector only for SHF_ALLOC'ed sections. For other sections,
+  // we handle relocations directly here.
+  auto *IS = dyn_cast<InputSection<ELFT>>(this);
+  if (IS && !(IS->Header->sh_flags & SHF_ALLOC)) {
+    for (const Elf_Shdr *RelSec : IS->RelocSections) {
+      if (RelSec->sh_type == SHT_RELA)
+        IS->relocateNonAlloc(Buf, IS->File->getObj().relas(RelSec));
+      else
+        IS->relocateNonAlloc(Buf, IS->File->getObj().rels(RelSec));
+    }
+    return;
+  }
+
   const unsigned Bits = sizeof(uintX_t) * 8;
   for (const Relocation &Rel : Relocations) {
     uintX_t Offset = Rel.Offset;

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=267917&r1=267916&r2=267917&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Thu Apr 28 13:42:04 2016
@@ -218,6 +218,9 @@ public:
   // Size of chunk with thunks code.
   uint64_t getThunksSize() const;
 
+  template <class RelTy>
+  void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
+
 private:
   template <class RelTy>
   void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=267917&r1=267916&r2=267917&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Apr 28 13:42:04 2016
@@ -532,12 +532,10 @@ template <class ELFT>
 template <class RelTy>
 void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
   uintX_t Flags = C.getSectionHdr()->sh_flags;
-  bool IsAlloc = Flags & SHF_ALLOC;
   bool IsWrite = Flags & SHF_WRITE;
 
   auto AddDyn = [=](const DynamicReloc<ELFT> &Reloc) {
-    if (IsAlloc)
-      Out<ELFT>::RelaDyn->addReloc(Reloc);
+    Out<ELFT>::RelaDyn->addReloc(Reloc);
   };
 
   const elf::ObjectFile<ELFT> &File = *C.getFile();
@@ -593,7 +591,7 @@ void Writer<ELFT>::scanRelocs(InputSecti
     // in a read-only section, we need to create a copy relocation for the
     // symbol.
     if (auto *B = dyn_cast<SharedSymbol<ELFT>>(&Body)) {
-      if (IsAlloc && !IsWrite && needsCopyRel(Expr, *B)) {
+      if (!IsWrite && needsCopyRel(Expr, *B)) {
         if (!B->needsCopy())
           addCopyRelSymbol(B);
         C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
@@ -630,10 +628,9 @@ void Writer<ELFT>::scanRelocs(InputSecti
 
       if (Target->UseLazyBinding) {
         Out<ELFT>::GotPlt->addEntry(Body);
-        if (IsAlloc)
-          Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
-                                        Body.getGotPltOffset<ELFT>(),
-                                        !Preemptible, &Body, 0});
+        Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
+                                      Body.getGotPltOffset<ELFT>(),
+                                      !Preemptible, &Body, 0});
       } else {
         if (Body.isInGot())
           continue;
@@ -744,17 +741,11 @@ template <class ELFT> void Writer<ELFT>:
   // Scan all relocations. Each relocation goes through a series
   // of tests to determine if it needs special treatment, such as
   // creating GOT, PLT, copy relocations, etc.
-  //
-  // The current code is a bit wasteful because it scans relocations
-  // in non-SHF_ALLOC sections. Such sections are never mapped to
-  // memory at runtime. Debug section is an example. Relocations in
-  // non-alloc sections are much easier to handle because it will
-  // never need complex treatement such as GOT or PLT (because at
-  // runtime no one refers them). We probably should skip non-alloc
-  // sections here and directly handle non-alloc relocations in
-  // writeTo function.
-  for (const Elf_Shdr *RelSec : C.RelocSections)
-    scanRelocs(C, *RelSec);
+  // Note that relocations for non-alloc sections are directly
+  // processed by InputSection::relocateNative.
+  if (C.getSectionHdr()->sh_flags & SHF_ALLOC)
+    for (const Elf_Shdr *RelSec : C.RelocSections)
+      scanRelocs(C, *RelSec);
 }
 
 template <class ELFT>

Modified: lld/trunk/test/ELF/relocation-non-alloc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-non-alloc.s?rev=267917&r1=267916&r2=267917&view=diff
==============================================================================
--- lld/trunk/test/ELF/relocation-non-alloc.s (original)
+++ lld/trunk/test/ELF/relocation-non-alloc.s Thu Apr 28 13:42:04 2016
@@ -33,7 +33,7 @@
 // CHECK-NEXT: AddressAlignment: 1
 // CHECK-NEXT: EntrySize: 0
 // CHECK-NEXT: SectionData (
-// CHECK-NEXT:   0000: 00100000 00000000 00000000 00000000
+// CHECK-NEXT:   0000: 00100000 00000000 00100000 00000000
 // CHECK-NEXT: )
 
 // CHECK:      Relocations [




More information about the llvm-commits mailing list