[lld] r196628 - Re-submit r195852 with GroupedSectionsPass change.

Rui Ueyama ruiu at google.com
Fri Dec 6 16:27:17 PST 2013


Author: ruiu
Date: Fri Dec  6 18:27:17 2013
New Revision: 196628

URL: http://llvm.org/viewvc/llvm-project?rev=196628&view=rev
Log:
Re-submit r195852 with GroupedSectionsPass change.

GroupedSectionsPass was a complicated pass. That pass's job was to reorder
atoms by section name, so that the atoms with the same section prefix will be
emitted consecutively to the executable. The pass added layout edges to atoms,
and let the layout pass to actually reorder them.

This patch simplifies the design by making GroupedSectionPass to directly
reorder atoms, rather than adding layout edges. This resembles ELF's
ArrayOrderPass.

This patch improves the performance of LLD; it used to take 7.1 seconds to
link LLD with LLD on my Macbook Pro, but it now takes 6.1 seconds.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/test/pecoff/Inputs/nonstandard-sections.obj.yaml
    lld/trunk/test/pecoff/lib.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h?rev=196628&r1=196627&r2=196628&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h Fri Dec  6 18:27:17 2013
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/PECOFF/GroupedSectionsPass.h-----------------------===//
+//===- lib/ReaderWriter/PECOFF/GroupedSectionsPass.h ----------------------===//
 //
 //                             The LLVM Linker
 //
@@ -7,9 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 ///
-/// \file \brief This pass adds layout-{before,after} references to atoms in
-/// grouped sections, so that they will appear in the correct order in the
-/// output.
+/// \file \brief This pass sorts atoms by section name, so that they will appear
+/// in the correct order in the output.
 ///
 /// In COFF, sections will be merged into one section by the linker if their
 /// names are the same after discarding the "$" character and all characters
@@ -25,13 +24,6 @@
 /// In this case, the resulting binary should have ".data" section with the
 /// contents of ".data", ".data$1", ".data$2" and ".data$3" in that order.
 ///
-/// In lld, this contraint is modeled by the atom model using
-/// layout-{before,after} references. Atoms in the same (unmerged-)section have
-/// already been connected with layout-{before,after} edges each other when the
-/// control reaches to this pass. We pick the head atom from each section that
-/// needs to merged, and connects them with layout-{before,after} edges in the
-/// right order, so that they'll be sorted correctly in the layout pass.
-///
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_READER_WRITER_PE_COFF_GROUPED_SECTIONS_PASS_H
@@ -39,103 +31,26 @@
 
 #include "Atoms.h"
 #include "lld/Core/Pass.h"
-#include "llvm/Support/Debug.h"
 
 #include <algorithm>
-#include <map>
-
-using lld::coff::COFFBaseDefinedAtom;
-using lld::coff::COFFDefinedAtom;
 
 namespace lld {
 namespace pecoff {
 
-namespace {
-bool compareByFileOrdinal(const DefinedAtom *a, const DefinedAtom *b) {
-  return a->file().ordinal() > b->file().ordinal();
-}
+static bool compare(const DefinedAtom *left, const DefinedAtom *right) {
+  if (left->sectionChoice() == DefinedAtom::sectionCustomRequired &&
+      right->sectionChoice() == DefinedAtom::sectionCustomRequired) {
+    return left->customSectionName().compare(right->customSectionName()) < 0;
+  }
+  return left->sectionChoice() == DefinedAtom::sectionCustomRequired &&
+    right->sectionChoice() != DefinedAtom::sectionCustomRequired;
 }
 
 class GroupedSectionsPass : public lld::Pass {
-public:
-  GroupedSectionsPass() {}
-
-  virtual void perform(std::unique_ptr<MutableFile> &mergedFile) {
-    std::map<StringRef, std::vector<COFFDefinedAtom *> > sectionToHeadAtoms(
-        filterHeadAtoms(*mergedFile));
-    std::vector<std::vector<COFFDefinedAtom *>> groupedAtomsList(
-        groupBySectionName(sectionToHeadAtoms));
-    for (auto &groupedAtoms : groupedAtomsList)
-      connectAtoms(groupedAtoms);
-  }
-
-private:
-  typedef std::map<StringRef, std::vector<COFFDefinedAtom *>> SectionToAtomsT;
-
-  /// Returns the list of atoms that appeared at the beginning of sections.
-  SectionToAtomsT filterHeadAtoms(MutableFile &mutableFile) const {
-    SectionToAtomsT result;
-    for (const DefinedAtom *atom : mutableFile.defined()) {
-      auto *coffAtom = dyn_cast<COFFDefinedAtom>((COFFBaseDefinedAtom *)atom);
-      if (coffAtom && coffAtom->ordinal() == 0)
-        result[coffAtom->customSectionName()].push_back(coffAtom);
-    }
-    return result;
-  }
-
-  /// Group atoms that needs to be merged. Returned atoms are sorted by section
-  /// name and file ordinal.
-  std::vector<std::vector<COFFDefinedAtom *>>
-  groupBySectionName(SectionToAtomsT sectionToHeadAtoms) const {
-    SectionToAtomsT res;
-    // Note that the atoms are already sorted by section name because std::map
-    // is a sorted map.
-    for (auto &i : sectionToHeadAtoms) {
-      StringRef sectionName = i.first;
-      std::vector<COFFDefinedAtom*> &atoms = i.second;
-      // Sections with the same name could exist if they are from different
-      // files. If that's the case, the sections needs to be sorted in the same
-      // order as they appeared in the command line.
-      std::stable_sort(atoms.begin(), atoms.end(), compareByFileOrdinal);
-      for (COFFDefinedAtom *atom : atoms) {
-        StringRef baseName = sectionName.split('$').first;
-        res[baseName].push_back(atom);
-      }
-    }
-    std::vector<std::vector<COFFDefinedAtom *>> vec;
-    for (auto &i : res)
-      vec.push_back(std::move(i.second));
-    return vec;
-  }
-
-  /// For each pair of atoms in the given vector, add a layout edge from the
-  /// follow-on tail of the first atom to the second atom. As a result, the
-  /// atoms in the vectors will be output as the same order as in the vector.
-  void connectAtoms(std::vector<COFFDefinedAtom *> heads) {
-    if (heads.empty())
-      return;
-    COFFDefinedAtom *tail = getTail(heads[0]);
-    for (auto i = heads.begin() + 1, e = heads.end(); i != e; ++i) {
-      COFFDefinedAtom *head = *i;
-      connectWithLayoutEdge(tail, head);
-      tail = getTail(head);
-    }
-  }
-
-  /// Follows the follow-on chain and returns the last atom.
-  COFFDefinedAtom *getTail(COFFDefinedAtom *atom) {
-    for (;;) {
-      COFFDefinedAtom *next = nullptr;
-      for (const Reference *r : *atom) {
-	if (r->kind() != lld::Reference::kindLayoutAfter)
-	  continue;
-	next = (COFFDefinedAtom *)(r->target());
-	break;
-      }
-      if (!next)
-	return atom;
-      atom = next;
-    }
+  public:
+  virtual void perform(std::unique_ptr<MutableFile> &file) {
+    auto definedAtoms = file->definedAtoms();
+    std::stable_sort(definedAtoms.begin(), definedAtoms.end(), compare);
   }
 };
 

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=196628&r1=196627&r2=196628&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Fri Dec  6 18:27:17 2013
@@ -238,8 +238,8 @@ uint32_t PECOFFLinkingContext::getSectio
 
 void PECOFFLinkingContext::addPasses(PassManager &pm) {
   pm.add(std::unique_ptr<Pass>(new pecoff::SetSubsystemPass(*this)));
-  pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass()));
   pm.add(std::unique_ptr<Pass>(new pecoff::IdataPass(*this)));
   pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+  pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass()));
 }
 } // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=196628&r1=196627&r2=196628&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Fri Dec  6 18:27:17 2013
@@ -157,6 +157,7 @@ private:
 
   mutable llvm::BumpPtrAllocator _alloc;
   const LinkingContext &_context;
+  uint64_t _ordinal;
 };
 
 class BumpPtrStringSaver : public llvm::cl::StringSaver {
@@ -279,7 +280,8 @@ DefinedAtom::Merge getMerge(const coff_a
 
 FileCOFF::FileCOFF(const LinkingContext &context,
                    std::unique_ptr<MemoryBuffer> mb, error_code &ec)
-    : File(mb->getBufferIdentifier(), kindObject), _context(context) {
+    : File(mb->getBufferIdentifier(), kindObject), _context(context),
+      _ordinal(0) {
   OwningPtr<llvm::object::Binary> bin;
   ec = llvm::object::createBinary(mb.release(), bin);
   if (ec)
@@ -457,7 +459,7 @@ error_code FileCOFF::createDefinedSymbol
       uint32_t size = sym->Value;
       auto *atom = new (_alloc)
           COFFBSSAtom(*this, name, getScope(sym), DefinedAtom::permRW_,
-                      DefinedAtom::mergeAsWeakAndAddressUsed, size, 0);
+                      DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++);
       result.push_back(atom);
       continue;
     }
@@ -565,7 +567,6 @@ FileCOFF::AtomizeDefinedSymbolsInSection
   StringRef sectionName;
   if (error_code ec = _obj->getSectionName(section, sectionName))
     return ec;
-  uint64_t ordinal = -1;
 
   // BSS section does not have contents. If this is the BSS section, create
   // COFFBSSAtom instead of COFFDefinedAtom.
@@ -576,7 +577,7 @@ FileCOFF::AtomizeDefinedSymbolsInSection
                                      : si[1]->Value - sym->Value;
       auto *atom = new (_alloc) COFFBSSAtom(
           *this, _symbolName[sym], getScope(sym), getPermissions(section),
-          DefinedAtom::mergeAsWeakAndAddressUsed, size, ++ordinal);
+          DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++);
       atoms.push_back(atom);
       _symbolAtom[sym] = atom;
     }
@@ -602,7 +603,7 @@ FileCOFF::AtomizeDefinedSymbolsInSection
     ArrayRef<uint8_t> data(secData.data(), secData.size());
     auto *atom = new (_alloc)
         COFFDefinedAtom(*this, "", sectionName, Atom::scopeTranslationUnit,
-                        type, isComdat, perms, _merge[section], data, 0);
+                        type, isComdat, perms, _merge[section], data, _ordinal++);
     atoms.push_back(atom);
     _definedAtomLocations[section][0].push_back(atom);
     return error_code::success();
@@ -615,7 +616,7 @@ FileCOFF::AtomizeDefinedSymbolsInSection
     ArrayRef<uint8_t> data(secData.data(), size);
     auto *atom = new (_alloc) COFFDefinedAtom(
         *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
-        perms, _merge[section], data, ++ordinal);
+        perms, _merge[section], data, _ordinal++);
     atoms.push_back(atom);
     _definedAtomLocations[section][0].push_back(atom);
   }
@@ -628,7 +629,7 @@ FileCOFF::AtomizeDefinedSymbolsInSection
     ArrayRef<uint8_t> data(start, end);
     auto *atom = new (_alloc) COFFDefinedAtom(
         *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat,
-        perms, _merge[section], data, ++ordinal);
+        perms, _merge[section], data, _ordinal++);
     atoms.push_back(atom);
     _symbolAtom[*si] = atom;
     _definedAtomLocations[section][(*si)->Value].push_back(atom);

Modified: lld/trunk/test/pecoff/Inputs/nonstandard-sections.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/nonstandard-sections.obj.yaml?rev=196628&r1=196627&r2=196628&view=diff
==============================================================================
--- lld/trunk/test/pecoff/Inputs/nonstandard-sections.obj.yaml (original)
+++ lld/trunk/test/pecoff/Inputs/nonstandard-sections.obj.yaml Fri Dec  6 18:27:17 2013
@@ -12,7 +12,7 @@ sections:
     Alignment:       4
     SectionData:     01234678
   - Name:            .foo
-    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE, IMAGE_SCN_MEM_EXECUTE ]
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE, IMAGE_SCN_MEM_EXECUTE ]
     Alignment:       4
     SectionData:     01234678
   - Name:            .bar

Modified: lld/trunk/test/pecoff/lib.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/lib.test?rev=196628&r1=196627&r2=196628&view=diff
==============================================================================
--- lld/trunk/test/pecoff/lib.test (original)
+++ lld/trunk/test/pecoff/lib.test Fri Dec  6 18:27:17 2013
@@ -5,8 +5,8 @@
 # RUN: lld -flavor link /out:%t1 /subsystem:console /entry:main /opt:noref \
 # RUN:   -- %t.obj %p/Inputs/static.lib && llvm-objdump -d %t1 | FileCheck %s
 
-CHECK: Disassembly of section .text:
-CHECK: .text:
-CHECK:     3000: a1 04 10 40 00      movl    4198404, %eax
-CHECK:     3005: 03 05 00 10 40 00   addl    4198400, %eax
-CHECK:     300b: c3                  ret
+CHECK:      Disassembly of section .text:
+CHECK-NEXT: .text:
+CHECK-NEXT:     movl 4198400, %eax
+CHECK-NEXT:     addl 4198404, %eax
+CHECK-NEXT:     ret





More information about the llvm-commits mailing list