ELF: Move section merging before ICF. NFCI.

Differential Revision: https://reviews.llvm.org/D34093

llvm-svn: 305176
This commit is contained in:
Peter Collingbourne 2017-06-12 00:00:51 +00:00
parent cf0e48ca01
commit dc7936eced
4 changed files with 68 additions and 65 deletions

View File

@ -36,6 +36,7 @@
#include "ScriptParser.h"
#include "Strings.h"
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Threads.h"
#include "Writer.h"
@ -43,7 +44,6 @@
#include "lld/Driver/Driver.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Path.h"
@ -1001,24 +1001,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (InputSectionBase *S : F->getSections())
InputSections.push_back(cast<InputSection>(S));
// Do size optimizations: garbage collection and identical code folding.
// This adds a .comment section containing a version string. We have to add it
// before decompressAndMergeSections because the .comment section is a
// mergeable section.
if (!Config->Relocatable)
InputSections.push_back(createCommentSection<ELFT>());
// Do size optimizations: garbage collection, merging of SHF_MERGE sections
// and identical code folding.
if (Config->GcSections)
markLive<ELFT>();
decompressAndMergeSections();
if (Config->ICF)
doIcf<ELFT>();
// MergeInputSection::splitIntoPieces needs to be called before
// any call of MergeInputSection::getOffset. Do that.
parallelForEach(InputSections.begin(), InputSections.end(),
[](InputSectionBase *S) {
if (!S->Live)
return;
if (Decompressor::isCompressedELFSection(S->Flags, S->Name))
S->uncompress();
if (auto *MS = dyn_cast<MergeInputSection>(S))
MS->splitIntoPieces();
});
// Write the result to the file.
writeResult<ELFT>();
}

View File

@ -29,6 +29,7 @@
#include "lld/Config/Version.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MD5.h"
@ -2133,7 +2134,6 @@ MergeSyntheticSection::MergeSyntheticSection(StringRef Name, uint32_t Type,
Builder(StringTableBuilder::RAW, Alignment) {}
void MergeSyntheticSection::addSection(MergeInputSection *MS) {
assert(!Finalized);
MS->Parent = this;
Sections.push_back(MS);
}
@ -2178,9 +2178,6 @@ void MergeSyntheticSection::finalizeNoTailMerge() {
}
void MergeSyntheticSection::finalizeContents() {
if (Finalized)
return;
Finalized = true;
if (shouldTailMerge())
finalizeTailMerge();
else
@ -2188,11 +2185,65 @@ void MergeSyntheticSection::finalizeContents() {
}
size_t MergeSyntheticSection::getSize() const {
// We should finalize string builder to know the size.
const_cast<MergeSyntheticSection *>(this)->finalizeContents();
return Builder.getSize();
}
// This function decompresses compressed sections and scans over the input
// sections to create mergeable synthetic sections. It removes
// MergeInputSections from the input section array and adds new synthetic
// sections at the location of the first input section that it replaces. It then
// finalizes each synthetic section in order to compute an output offset for
// each piece of each input section.
void elf::decompressAndMergeSections() {
// splitIntoPieces needs to be called on each MergeInputSection before calling
// finalizeContents(). Do that first.
parallelForEach(InputSections.begin(), InputSections.end(),
[](InputSectionBase *S) {
if (!S->Live)
return;
if (Decompressor::isCompressedELFSection(S->Flags, S->Name))
S->uncompress();
if (auto *MS = dyn_cast<MergeInputSection>(S))
MS->splitIntoPieces();
});
std::vector<MergeSyntheticSection *> MergeSections;
for (InputSectionBase *&S : InputSections) {
MergeInputSection *MS = dyn_cast<MergeInputSection>(S);
if (!MS)
continue;
// We do not want to handle sections that are not alive, so just remove
// them instead of trying to merge.
if (!MS->Live)
continue;
StringRef OutsecName = getOutputSectionName(MS->Name);
uint64_t Flags = MS->Flags & ~(uint64_t)SHF_GROUP;
uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
return Sec->Name == OutsecName && Sec->Flags == Flags &&
Sec->Alignment == Alignment;
});
if (I == MergeSections.end()) {
MergeSyntheticSection *Syn =
make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment);
MergeSections.push_back(Syn);
I = std::prev(MergeSections.end());
S = Syn;
} else {
S = nullptr;
}
(*I)->addSection(MS);
}
for (auto *MS : MergeSections)
MS->finalizeContents();
std::vector<InputSectionBase *> &V = InputSections;
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
}
MipsRldMapSection::MipsRldMapSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize,
".rld_map") {}

View File

@ -651,7 +651,6 @@ private:
void finalizeTailMerge();
void finalizeNoTailMerge();
bool Finalized = false;
llvm::StringTableBuilder Builder;
std::vector<MergeInputSection *> Sections;
};
@ -748,6 +747,7 @@ private:
template <class ELFT> InputSection *createCommonSection();
InputSection *createInterpSection();
template <class ELFT> MergeInputSection *createCommentSection();
void decompressAndMergeSections();
SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
uint64_t Size, InputSectionBase *Section);

View File

@ -137,46 +137,6 @@ template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() {
Phdrs.erase(I, Phdrs.end());
}
// This function scans over the input sections and creates mergeable
// synthetic sections. It removes MergeInputSections from array and
// adds new synthetic ones. Each synthetic section is added to the
// location of the first input section it replaces.
static void combineMergableSections() {
std::vector<MergeSyntheticSection *> MergeSections;
for (InputSectionBase *&S : InputSections) {
MergeInputSection *MS = dyn_cast<MergeInputSection>(S);
if (!MS)
continue;
// We do not want to handle sections that are not alive, so just remove
// them instead of trying to merge.
if (!MS->Live)
continue;
StringRef OutsecName = getOutputSectionName(MS->Name);
uint64_t Flags = MS->Flags & ~(uint64_t)SHF_GROUP;
uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
return Sec->Name == OutsecName && Sec->Flags == Flags &&
Sec->Alignment == Alignment;
});
if (I == MergeSections.end()) {
MergeSyntheticSection *Syn =
make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment);
MergeSections.push_back(Syn);
I = std::prev(MergeSections.end());
S = Syn;
} else {
S = nullptr;
}
(*I)->addSection(MS);
}
std::vector<InputSectionBase *> &V = InputSections;
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
}
template <class ELFT> static void combineEhFrameSections() {
for (InputSectionBase *&S : InputSections) {
EhInputSection *ES = dyn_cast<EhInputSection>(S);
@ -205,7 +165,6 @@ template <class ELFT> void Writer<ELFT>::run() {
// Create linker-synthesized sections such as .got or .plt.
// Such sections are of type input section.
createSyntheticSections();
combineMergableSections();
if (!Config->Relocatable)
combineEhFrameSections<ELFT>();
@ -340,9 +299,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
InX::Interp = nullptr;
}
if (!Config->Relocatable)
Add(createCommentSection<ELFT>());
if (Config->Strip != StripPolicy::All) {
InX::StrTab = make<StringTableSection>(".strtab", false);
InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab);