summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
authorShankar Easwaran <shankare@codeaurora.org>2015-03-20 23:47:03 +0000
committerShankar Easwaran <shankare@codeaurora.org>2015-03-20 23:47:03 +0000
commit07f6ce0b83ac97879e2d1010c329158ee6db17b8 (patch)
tree1ec21b9ea0188fe9cc9c6785f25d8911f5589606 /lld/lib/ReaderWriter
parent33c979d685e35ac8ac813543c0ccc70a7ec392f8 (diff)
downloadbcm5719-llvm-07f6ce0b83ac97879e2d1010c329158ee6db17b8.tar.gz
bcm5719-llvm-07f6ce0b83ac97879e2d1010c329158ee6db17b8.zip
[ELF] OrderPass : Order atoms only by ordinals.
Move the init array/fini array sorting to the Output ELF writer. AFAIK, this is only needed by the X86_64/ARM ABI. This shaves time taken to self host lld by 0.2 seconds. Before patch ---------------- 4791.062059 task-clock # 1.634 CPUs utilized ( +- 0.28% ) 61,107 context-switches # 0.013 M/sec ( +- 0.56% ) 2.932902671 seconds time elapsed ( +- 0.84% ) After patch ------------- 4608.417248 task-clock # 1.669 CPUs utilized ( +- 0.30% ) 61,616 context-switches # 0.013 M/sec ( +- 0.63% ) 2.761012703 seconds time elapsed ( +- 0.63% ) llvm-svn: 232866
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h55
-rw-r--r--lld/lib/ReaderWriter/ELF/OrderPass.h40
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h5
3 files changed, 62 insertions, 38 deletions
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index 05c7cddc66a..de03ce1cb60 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -316,13 +316,25 @@ public:
return _copiedDynSymNames.count(sla->name());
}
+ /// \brief Handle SORT_BY_PRIORITY.
+ void sortOutputSectionByPriority(StringRef outputSectionName,
+ StringRef prefix);
+
protected:
+ /// \brief TargetLayouts may use these functions to reorder the input sections
+ /// in a order defined by their ABI.
+ virtual void finalizeOutputSectionLayout() {}
+
/// \brief Allocate a new section.
virtual AtomSection<ELFT> *createSection(
StringRef name, int32_t contentType,
DefinedAtom::ContentPermissions contentPermissions,
SectionOrder sectionOrder);
+private:
+ /// Helper function that returns the priority value from an input section.
+ uint32_t getPriorityFromSectionName(StringRef sectionName) const;
+
protected:
llvm::BumpPtrAllocator _allocator;
SectionMapT _sectionMap;
@@ -657,13 +669,56 @@ template <class ELFT> void DefaultLayout<ELFT>::createOutputSections() {
}
}
+template <class ELFT>
+uint32_t
+DefaultLayout<ELFT>::getPriorityFromSectionName(StringRef sectionName) const {
+ StringRef priority = sectionName.drop_front().rsplit('.').second;
+ uint32_t prio;
+ if (priority.getAsInteger(10, prio))
+ return std::numeric_limits<uint32_t>::max();
+ return prio;
+}
+
+template <class ELFT>
+void DefaultLayout<ELFT>::sortOutputSectionByPriority(
+ StringRef outputSectionName, StringRef prefix) {
+ OutputSection<ELFT> *outputSection = findOutputSection(outputSectionName);
+ if (!outputSection)
+ return;
+
+ auto sections = outputSection->sections();
+
+ std::sort(sections.begin(), sections.end(),
+ [&](Chunk<ELFT> *lhs, Chunk<ELFT> *rhs) {
+ Section<ELFT> *lhsSection = dyn_cast<Section<ELFT>>(lhs);
+ Section<ELFT> *rhsSection = dyn_cast<Section<ELFT>>(rhs);
+ if (!lhsSection || !rhsSection)
+ return false;
+ StringRef lhsSectionName = lhsSection->inputSectionName();
+ StringRef rhsSectionName = rhsSection->inputSectionName();
+
+ if (!prefix.empty()) {
+ if (!lhsSectionName.startswith(prefix) ||
+ !rhsSectionName.startswith(prefix))
+ return false;
+ }
+ return getPriorityFromSectionName(lhsSectionName) <
+ getPriorityFromSectionName(rhsSectionName);
+ });
+};
+
template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
ELFLinkingContext::OutputMagic outputMagic = _context.getOutputMagic();
// sort the sections by their order as defined by the layout
sortInputSections();
+
// Create output sections.
createOutputSections();
+
+ // Finalize output section layout.
+ finalizeOutputSectionLayout();
+
// Set the ordinal after sorting the sections
int ordinal = 1;
for (auto osi : _outputSections) {
diff --git a/lld/lib/ReaderWriter/ELF/OrderPass.h b/lld/lib/ReaderWriter/ELF/OrderPass.h
index 0948485c7bf..d126b830db9 100644
--- a/lld/lib/ReaderWriter/ELF/OrderPass.h
+++ b/lld/lib/ReaderWriter/ELF/OrderPass.h
@@ -17,49 +17,13 @@ namespace lld {
namespace elf {
/// \brief This pass sorts atoms by file and atom ordinals.
-/// .{init,fini}_array.<priority> sections are handled specially.
class OrderPass : public Pass {
public:
void perform(std::unique_ptr<MutableFile> &file) override {
- MutableFile::DefinedAtomRange defined = file->definedAtoms();
- auto last = std::partition(defined.begin(), defined.end(), isInitFini);
- parallel_sort(defined.begin(), last, compareInitFini);
- parallel_sort(last, defined.end(), DefinedAtom::compareByPosition);
- }
-
-private:
- static bool isInitFini(const DefinedAtom *atom) {
- if (atom->sectionChoice() != DefinedAtom::sectionCustomRequired)
- return false;
- StringRef name = atom->customSectionName();
- return name.startswith(".init_array") || name.startswith(".fini_array");
- }
-
- // Parses the number in .{init,fini}_array.<number>.
- // Returns UINT32_MAX by default.
- static uint32_t getPriority(const DefinedAtom *atom) {
- StringRef sec = atom->customSectionName();
- StringRef num = sec.drop_front().rsplit('.').second;
- uint32_t prio;
- if (num.getAsInteger(10, prio))
- return std::numeric_limits<uint32_t>::max();
- return prio;
- }
-
- static bool compareInitFini(const DefinedAtom *lhs, const DefinedAtom *rhs) {
- // Sort {.init_array, .fini_array}[.<num>] sections
- // according to their number. Sections without optional
- // numer suffix should go last.
- uint32_t lp = getPriority(lhs);
- uint32_t rp = getPriority(rhs);
- if (lp != rp)
- return lp < rp;
-
- // If both atoms have the same priority, fall back to default.
- return DefinedAtom::compareByPosition(lhs, rhs);
+ parallel_sort(file->definedAtoms().begin(), file->definedAtoms().end(),
+ DefinedAtom::compareByPosition);
}
};
-
}
}
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
index 24cdd9850c4..57da7bca01e 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
@@ -24,6 +24,11 @@ class X86_64TargetLayout : public TargetLayout<X86_64ELFType> {
public:
X86_64TargetLayout(X86_64LinkingContext &context)
: TargetLayout(context) {}
+
+ void finalizeOutputSectionLayout() override {
+ sortOutputSectionByPriority(".init_array", ".init_array");
+ sortOutputSectionByPriority(".fini_array", ".fini_array");
+ }
};
class X86_64TargetHandler
OpenPOWER on IntegriCloud