[lld] r276146 - Create thunks before regular relocation scan.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 10:58:08 PDT 2016


Author: rafael
Date: Wed Jul 20 12:58:07 2016
New Revision: 276146

URL: http://llvm.org/viewvc/llvm-project?rev=276146&view=rev
Log:
Create thunks before regular relocation scan.

We will need to do something like this to support range extension
thunks since that process is iterative.

Doing this also has the advantage that when doing the regular
relocation scan the offset in the output section is known and we can
just store that. This reduces the number of times we have to run
getOffset and I think will allow a more specialized .eh_frame
representation.

By itself this is already a performance win.

firefox
  master 7.295045737
  patch  7.209466989 0.98826892235
chromium
  master 4.531254468
  patch  4.509221804 0.995137623774
chromium fast
  master 1.836928973
  patch  1.823805241 0.992855612714
the gold plugin
  master 0.379768791
  patch  0.380043405 1.00072310839
clang
  master 0.642698284
  patch  0.642215663 0.999249070657
llvm-as
  master 0.036665467
  patch  0.036456225 0.994293213284
the gold plugin fsds
  master 0.40395817
  patch  0.404384555 1.0010555177
clang fsds
  master 0.722045545
  patch  0.720946135 0.998477367518
llvm-as fsds
  master 0.03292646
  patch  0.032759965 0.994943428477
scylla
  master 3.427376378
  patch  3.368316181 0.98276810292

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Jul 20 12:58:07 2016
@@ -338,7 +338,7 @@ void InputSectionBase<ELFT>::relocate(ui
 
   const unsigned Bits = sizeof(uintX_t) * 8;
   for (const Relocation<ELFT> &Rel : Relocations) {
-    uintX_t Offset = Rel.InputSec->getOffset(Rel.Offset);
+    uintX_t Offset = Rel.Offset;
     uint8_t *BufLoc = Buf + Offset;
     uint32_t Type = Rel.Type;
     uintX_t A = Rel.Addend;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Jul 20 12:58:07 2016
@@ -1278,7 +1278,7 @@ template <class ELFT>
 typename ELFT::uint DynamicReloc<ELFT>::getOffset() const {
   if (OutputSec)
     return OutputSec->getVA() + OffsetInSec;
-  return InputSec->OutSec->getVA() + InputSec->getOffset(OffsetInSec);
+  return InputSec->OutSec->getVA() + OffsetInSec;
 }
 
 template <class ELFT>

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jul 20 12:58:07 2016
@@ -548,9 +548,19 @@ static void scanRelocs(InputSectionBase<
     while (PieceI != PieceE &&
            (PieceI->InputOff + PieceI->size() <= RI.r_offset))
       ++PieceI;
-    if (PieceI != PieceE && PieceI->InputOff <= RI.r_offset &&
-        PieceI->OutputOff == (uintX_t)-1)
-      continue;
+
+    // Compute the offset of this section in the output section. We do it here
+    // to try to compute it only once.
+    uintX_t Offset;
+    if (PieceI != PieceE) {
+      assert(PieceI->InputOff <= RI.r_offset && "Relocation not in any piece");
+      if (PieceI->OutputOff == (uintX_t)-1)
+        continue;
+      Offset = PieceI->OutputOff + RI.r_offset - PieceI->InputOff;
+      assert(Offset == C.getOffset(RI.r_offset));
+    } else {
+      Offset = C.getOffset(RI.r_offset);
+    }
 
     // This relocation does not require got entry, but it is relative to got and
     // needs it to be created. Here we request for that.
@@ -559,8 +569,8 @@ static void scanRelocs(InputSectionBase<
 
     uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body);
 
-    if (unsigned Processed = handleTlsRelocation<ELFT>(
-            Type, Body, C, RI.r_offset, Addend, Expr)) {
+    if (unsigned Processed =
+            handleTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr)) {
       I += (Processed - 1);
       continue;
     }
@@ -581,17 +591,17 @@ static void scanRelocs(InputSectionBase<
       // relocation. We can process some of it and and just ask the dynamic
       // linker to add the load address.
       if (!Constant)
-        AddDyn({Target->RelativeRel, &C, RI.r_offset, true, &Body, Addend});
+        AddDyn({Target->RelativeRel, &C, Offset, true, &Body, Addend});
 
       // If the produced value is a constant, we just remember to write it
       // when outputting this section. We also have to do it if the format
       // uses Elf_Rel, since in that case the written value is the addend.
       if (Constant || !RelTy::IsRela)
-        C.Relocations.push_back({Expr, Type, &C, RI.r_offset, Addend, &Body});
+        C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
     } else {
       // We don't know anything about the finaly symbol. Just ask the dynamic
       // linker to handle the relocation for us.
-      AddDyn({Target->getDynRel(Type), &C, RI.r_offset, false, &Body, Addend});
+      AddDyn({Target->getDynRel(Type), &C, Offset, false, &Body, Addend});
       // MIPS ABI turns using of GOT and dynamic relocations inside out.
       // While regular ABI uses dynamic relocations to fill up GOT entries
       // MIPS ABI requires dynamic linker to fills up GOT entries using
@@ -612,14 +622,6 @@ static void scanRelocs(InputSectionBase<
       continue;
     }
 
-    // Some targets might require creation of thunks for relocations.
-    // Now we support only MIPS which requires LA25 thunk to call PIC
-    // code from non-PIC one, and ARM which requires interworking.
-    if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC) {
-      auto *Sec = cast<InputSection<ELFT>>(&C);
-      addThunk<ELFT>(Type, Body, *Sec);
-    }
-
     // At this point we are done with the relocated position. Some relocations
     // also require us to create a got or plt entry.
 
@@ -676,19 +678,6 @@ static void scanRelocs(InputSectionBase<
   }
 }
 
-template <class ELFT> void scanRelocations(InputSection<ELFT> &C) {
-  typedef typename ELFT::Shdr Elf_Shdr;
-
-  // 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.
-  // Note that relocations for non-alloc sections are directly
-  // processed by InputSection::relocateNonAlloc.
-  if (C.getSectionHdr()->sh_flags & SHF_ALLOC)
-    for (const Elf_Shdr *RelSec : C.RelocSections)
-      scanRelocations(C, *RelSec);
-}
-
 template <class ELFT>
 void scanRelocations(InputSectionBase<ELFT> &S,
                      const typename ELFT::Shdr &RelSec) {
@@ -699,10 +688,35 @@ void scanRelocations(InputSectionBase<EL
     scanRelocs(S, EObj.rels(&RelSec));
 }
 
-template void scanRelocations<ELF32LE>(InputSection<ELF32LE> &);
-template void scanRelocations<ELF32BE>(InputSection<ELF32BE> &);
-template void scanRelocations<ELF64LE>(InputSection<ELF64LE> &);
-template void scanRelocations<ELF64BE>(InputSection<ELF64BE> &);
+template <class ELFT, class RelTy>
+static void createThunks(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
+  const elf::ObjectFile<ELFT> &File = *C.getFile();
+  for (const RelTy &Rel : Rels) {
+    SymbolBody &Body = File.getRelocTargetSym(Rel);
+    uint32_t Type = Rel.getType(Config->Mips64EL);
+    RelExpr Expr = Target->getRelExpr(Type, Body);
+    if (!isPreemptible(Body, Type) && needsPlt(Expr))
+      Expr = fromPlt(Expr);
+    Expr = Target->getThunkExpr(Expr, Type, File, Body);
+    // Some targets might require creation of thunks for relocations.
+    // Now we support only MIPS which requires LA25 thunk to call PIC
+    // code from non-PIC one, and ARM which requires interworking.
+    if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC) {
+      auto *Sec = cast<InputSection<ELFT>>(&C);
+      addThunk<ELFT>(Type, Body, *Sec);
+    }
+  }
+}
+
+template <class ELFT>
+void createThunks(InputSectionBase<ELFT> &S,
+                  const typename ELFT::Shdr &RelSec) {
+  ELFFile<ELFT> &EObj = S.getFile()->getObj();
+  if (RelSec.sh_type == SHT_RELA)
+    createThunks(S, EObj.relas(&RelSec));
+  else
+    createThunks(S, EObj.rels(&RelSec));
+}
 
 template void scanRelocations<ELF32LE>(InputSectionBase<ELF32LE> &,
                                        const ELF32LE::Shdr &);
@@ -712,5 +726,14 @@ template void scanRelocations<ELF64LE>(I
                                        const ELF64LE::Shdr &);
 template void scanRelocations<ELF64BE>(InputSectionBase<ELF64BE> &,
                                        const ELF64BE::Shdr &);
+
+template void createThunks<ELF32LE>(InputSectionBase<ELF32LE> &,
+                                    const ELF32LE::Shdr &);
+template void createThunks<ELF32BE>(InputSectionBase<ELF32BE> &,
+                                    const ELF32BE::Shdr &);
+template void createThunks<ELF64LE>(InputSectionBase<ELF64LE> &,
+                                    const ELF64LE::Shdr &);
+template void createThunks<ELF64BE>(InputSectionBase<ELF64BE> &,
+                                    const ELF64BE::Shdr &);
 }
 }

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Jul 20 12:58:07 2016
@@ -73,12 +73,13 @@ template <class ELFT> struct Relocation
   SymbolBody *Sym;
 };
 
-template <class ELFT> void scanRelocations(InputSection<ELFT> &);
-
 template <class ELFT>
 void scanRelocations(InputSectionBase<ELFT> &, const typename ELFT::Shdr &);
 
 template <class ELFT>
+void createThunks(InputSectionBase<ELFT> &, const typename ELFT::Shdr &);
+
+template <class ELFT>
 static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) {
   return 0;
 }

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Jul 20 12:58:07 2016
@@ -1496,6 +1496,7 @@ ARMTargetInfo::ARMTargetInfo() {
   PltHeaderSize = 20;
   // ARM uses Variant 1 TLS
   TcbSize = 8;
+  NeedsThunks = true;
 }
 
 RelExpr ARMTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
@@ -1836,6 +1837,7 @@ template <class ELFT> MipsTargetInfo<ELF
   PltHeaderSize = 32;
   CopyRel = R_MIPS_COPY;
   PltRel = R_MIPS_JUMP_SLOT;
+  NeedsThunks = true;
   if (ELFT::Is64Bits) {
     RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
     TlsGotRel = R_MIPS_TLS_TPREL64;

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Jul 20 12:58:07 2016
@@ -92,6 +92,8 @@ public:
   // Set to 0 for variant 2
   unsigned TcbSize = 0;
 
+  bool NeedsThunks = false;
+
   virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
                                   RelExpr Expr) const;
   virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=276146&r1=276145&r2=276146&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Jul 20 12:58:07 2016
@@ -49,6 +49,9 @@ private:
   void copyLocalSymbols();
   void addReservedSymbols();
   std::vector<OutputSectionBase<ELFT> *> createSections();
+  void forEachRelSec(
+      std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
+          Fn);
   void finalizeSections();
   void addPredefinedSections();
   bool needsGot();
@@ -633,6 +636,34 @@ template <class ELFT> static void sortCt
 }
 
 template <class ELFT>
+void Writer<ELFT>::forEachRelSec(
+    std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
+        Fn) {
+  for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+       Symtab.getObjectFiles()) {
+    for (InputSectionBase<ELFT> *C : F->getSections()) {
+      if (isDiscarded(C))
+        continue;
+      // 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.
+      // Note that relocations for non-alloc sections are directly
+      // processed by InputSection::relocateNonAlloc.
+      if (!(C->getSectionHdr()->sh_flags & SHF_ALLOC))
+        continue;
+      if (auto *S = dyn_cast<InputSection<ELFT>>(C)) {
+        for (const Elf_Shdr *RelSec : S->RelocSections)
+          Fn(*S, *RelSec);
+        continue;
+      }
+      if (auto *S = dyn_cast<EhInputSection<ELFT>>(C))
+        if (S->RelocSection)
+          Fn(*S, *S->RelocSection);
+    }
+  }
+}
+
+template <class ELFT>
 std::vector<OutputSectionBase<ELFT> *> Writer<ELFT>::createSections() {
   std::vector<OutputSectionBase<ELFT> *> Result;
 
@@ -705,26 +736,16 @@ template <class ELFT> void Writer<ELFT>:
     Out<ELFT>::EhFrame->finalize();
   }
 
-  // Scan relocations. This must be done after every symbol is declared so that
-  // we can correctly decide if a dynamic relocation is needed.
-  for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
-       Symtab.getObjectFiles()) {
-    for (InputSectionBase<ELFT> *C : F->getSections()) {
-      if (isDiscarded(C))
-        continue;
-      if (auto *S = dyn_cast<InputSection<ELFT>>(C)) {
-        scanRelocations(*S);
-        continue;
-      }
-      if (auto *S = dyn_cast<EhInputSection<ELFT>>(C))
-        if (S->RelocSection)
-          scanRelocations(*S, *S->RelocSection);
-    }
-  }
+  if (Target->NeedsThunks)
+    forEachRelSec(createThunks<ELFT>);
 
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Sec->assignOffsets();
 
+  // Scan relocations. This must be done after every symbol is declared so that
+  // we can correctly decide if a dynamic relocation is needed.
+  forEachRelSec(scanRelocations<ELFT>);
+
   // Now that we have defined all possible symbols including linker-
   // synthesized ones. Visit all symbols to give the finishing touches.
   std::vector<DefinedCommon *> CommonSymbols;




More information about the llvm-commits mailing list