[PATCH] [lld][Driver] Parallelize reading initial object files.

Michael Spencer bigcheesegs at gmail.com
Fri Apr 19 17:31:31 PDT 2013


  Address comments and split out reader fix.

Hi shankarke, kledzik,

http://llvm-reviews.chandlerc.com/D664

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D664?vs=1614&id=1699#toc

Files:
  lib/Driver/Driver.cpp
  lib/ReaderWriter/ELF/File.h

Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -8,10 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
+
 #include "lld/Core/LLVM.h"
 #include "lld/Core/InputFiles.h"
-#include "lld/Core/Resolver.h"
 #include "lld/Core/PassManager.h"
+#include "lld/Core/Parallel.h"
+#include "lld/Core/Resolver.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "lld/ReaderWriter/Writer.h"
 
@@ -39,20 +41,33 @@
   }
 
   // Read inputs
-  InputFiles inputs;
+  std::vector<std::vector<std::unique_ptr<File>>> files(
+      targetInfo.inputFiles().size());
+  size_t index = 0;
+  std::atomic<bool> fail(false);
+  TaskGroup tg;
   for (const auto &input : targetInfo.inputFiles()) {
-    std::vector<std::unique_ptr<File>> files;
     if (targetInfo.logInputFiles())
       llvm::outs() << input.getPath() << "\n";
-      
-    error_code ec = targetInfo.readFile(input.getPath(), files);
-    if (ec) {
-      diagnostics   << "Failed to read file: " << input.getPath() << ": "
-                    << ec.message() << "\n";
-      return true;
-    }
-    inputs.appendFiles(files);
+
+    tg.spawn([&, index] {
+      if (error_code ec = targetInfo.readFile(input.getPath(), files[index])) {
+        diagnostics << "Failed to read file: " << input.getPath()
+                    << ": " << ec.message() << "\n";
+        fail = true;
+        return;
+      }
+    });
+    ++index;
   }
+  tg.sync();
+
+  if (fail)
+    return true;
+
+  InputFiles inputs;
+  for (auto &f : files)
+    inputs.appendFiles(f);
 
   // Give target a chance to add files.
   targetInfo.addImplicitFiles(inputs);
Index: lib/ReaderWriter/ELF/File.h
===================================================================
--- lib/ReaderWriter/ELF/File.h
+++ lib/ReaderWriter/ELF/File.h
@@ -114,6 +114,8 @@
   typedef std::unordered_map<MergeSectionKey, DefinedAtom *, MergeSectionEq,
                              MergeSectionEq> MergedSectionMapT;
   typedef typename MergedSectionMapT::iterator MergedSectionMapIterT;
+  typedef llvm::DenseMap<const Elf_Shdr *, std::vector<const Elf_Sym *>>
+      SectionSymbolsT;
 
 public:
   ELFFile(const ELFTargetInfo &ti, StringRef name)
@@ -140,7 +142,8 @@
 
     binaryFile.take();
 
-    std::map<const Elf_Shdr *, std::vector<const Elf_Sym *> > sectionSymbols;
+    /// \brief Map from sections to a list of symbols that section contains.
+    SectionSymbolsT sectionSymbols;
 
     // Sections that have merge string property
     std::vector<const Elf_Shdr *> mergeStringSections;
@@ -308,24 +311,37 @@
       }
     }
 
+    // Iterate over sections by object file position. The pointers point into
+    // the memory mapped file, so it's valid to sort based on them.
+    std::vector<typename SectionSymbolsT::value_type *> secSyms;
+    secSyms.reserve(sectionSymbols.size());
     for (auto &i : sectionSymbols) {
-      auto &symbols = i.second;
+      secSyms.push_back(&i);
+    }
+    std::sort(secSyms.begin(), secSyms.end(),
+              [](const typename SectionSymbolsT::value_type *a,
+                 const typename SectionSymbolsT::value_type *b) {
+       return a->first < b->first;
+    });
+
+    for (auto &i : secSyms) {
+      auto &symbols = i->second;
       // Sort symbols by position.
       std::stable_sort(symbols.begin(), symbols.end(),
                        [](const Elf_Sym * A, const Elf_Sym * B) {
         return A->st_value < B->st_value;
       });
 
       StringRef sectionContents;
-      if ((EC = _objFile->getSectionContents(i.first, sectionContents)))
+      if ((EC = _objFile->getSectionContents(i->first, sectionContents)))
         return;
 
       StringRef sectionName;
-      if ((EC = _objFile->getSectionName(i.first, sectionName)))
+      if ((EC = _objFile->getSectionName(i->first, sectionName)))
         return;
 
       // If the section has no symbols, create a custom atom for it.
-      if (i.first->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() &&
+      if (i->first->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() &&
           !sectionContents.empty()) {
         Elf_Sym *sym = new (_readerStorage) Elf_Sym;
         sym->st_name = 0;
@@ -337,7 +353,7 @@
         ArrayRef<uint8_t> content((const uint8_t *)sectionContents.data(),
                                   sectionContents.size());
         auto newAtom = new (_readerStorage)
-            ELFDefinedAtom<ELFT>(*this, sectionName, sectionName, sym, i.first,
+            ELFDefinedAtom<ELFT>(*this, sectionName, sectionName, sym, i->first,
                                  content, 0, 0, _references);
         newAtom->setOrdinal(++ordinal);
         _definedAtoms._atoms.push_back(newAtom);
@@ -350,10 +366,10 @@
       ELFReference<ELFT> *anonPrecededBy = nullptr;
       ELFReference<ELFT> *anonFollowedBy = nullptr;
 
-      // i.first is the section the symbol lives in
+      // i->first is the section the symbol lives in
       for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
         StringRef symbolName;
-        if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
+        if ((EC = _objFile->getSymbolName(i->first, *si, symbolName)))
           return;
 
         const Elf_Shdr *section = _objFile->getSection(*si);
@@ -378,7 +394,7 @@
         uint64_t contentSize;
         if (si + 1 == se) {
           // if this is the last symbol, take up the remaining data.
-          contentSize = isCommon ? 0 : i.first->sh_size - (*si)->st_value;
+          contentSize = isCommon ? 0 : i->first->sh_size - (*si)->st_value;
         } else {
           contentSize = isCommon ? 0 : (*(si + 1))->st_value - (*si)->st_value;
         }
@@ -412,7 +428,7 @@
           *sym = **si;
           sym->setBinding(llvm::ELF::STB_GLOBAL);
           anonAtom = createDefinedAtomAndAssignRelocations(
-              "", sectionName, sym, i.first,
+              "", sectionName, sym, i->first,
               ArrayRef<uint8_t>(
                   (uint8_t *)sectionContents.data() + (*si)->st_value,
                   contentSize));
@@ -457,7 +473,7 @@
         }
 
         auto newAtom = createDefinedAtomAndAssignRelocations(
-            symbolName, sectionName, *si, i.first, symbolData);
+            symbolName, sectionName, *si, i->first, symbolData);
 
         newAtom->setOrdinal(++ordinal);
 
@@ -584,7 +600,7 @@
               (rai.r_offset < symbol->st_value + content.size())))
           continue;
         bool isMips64EL = _objFile->isMips64EL();
-        Kind kind = (Kind) rai.getType(isMips64EL);
+        Reference::Kind kind = (Reference::Kind) rai.getType(isMips64EL);
         uint32_t symbolIndex = rai.getSymbol(isMips64EL);
         auto *ERef = new (_readerStorage)
             ELFReference<ELFT>(&rai, rai.r_offset - symbol->st_value, nullptr,
@@ -598,7 +614,7 @@
         if ((ri.r_offset >= symbol->st_value) &&
             (ri.r_offset < symbol->st_value + content.size())) {
           bool isMips64EL = _objFile->isMips64EL();
-          Kind kind = (Kind) ri.getType(isMips64EL);
+          Reference::Kind kind = (Reference::Kind) ri.getType(isMips64EL);
           uint32_t symbolIndex = ri.getSymbol(isMips64EL);
           auto *ERef = new (_readerStorage)
               ELFReference<ELFT>(&ri, ri.r_offset - symbol->st_value, nullptr,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D664.2.patch
Type: text/x-patch
Size: 7453 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130419/f2e48000/attachment.bin>


More information about the llvm-commits mailing list