[lld] r270455 - Do not split mergeable sections if they are gc'ed.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Mon May 23 09:55:47 PDT 2016
Author: ruiu
Date: Mon May 23 11:55:43 2016
New Revision: 270455
URL: http://llvm.org/viewvc/llvm-project?rev=270455&view=rev
Log:
Do not split mergeable sections if they are gc'ed.
Previously, mergeable section's constructors did more than just
setting member variables; it split section contents into small
pieces. It is not always computationally cheap task because if
the section is a mergeable string section, it needs to scan the
entire section to split them by NUL characters.
If a section would be thrown away by GC, that cost ended up
being a waste of time. It is going to be larger problem if the
section is compressed -- the whole time to uncompress it and
split it up is going to be a waste.
Luckily, we can defer section splitting after GC. We just have
to remember which offsets are in use during GC and apply that later.
This patch implements it.
Differential Revision: http://reviews.llvm.org/D20516
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/MarkLive.cpp
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=270455&r1=270454&r2=270455&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Mon May 23 11:55:43 2016
@@ -12,6 +12,7 @@
#include "Error.h"
#include "ICF.h"
#include "InputFiles.h"
+#include "InputSection.h"
#include "LinkerScript.h"
#include "SymbolListFile.h"
#include "SymbolTable.h"
@@ -507,5 +508,15 @@ template <class ELFT> void LinkerDriver:
markLive<ELFT>();
if (Config->ICF)
doIcf<ELFT>();
+
+ // MergeInputSection::splitIntoPieces needs to be called before
+ // any call of MergeInputSection::getOffset. Do that.
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles())
+ for (InputSectionBase<ELFT> *S : F->getSections())
+ if (S && S != &InputSection<ELFT>::Discarded && S->Live)
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
+ MS->splitIntoPieces();
+
writeResult<ELFT>(&Symtab);
}
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=270455&r1=270454&r2=270455&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon May 23 11:55:43 2016
@@ -501,13 +501,19 @@ static std::vector<SectionPiece> splitNo
template <class ELFT>
MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F,
const Elf_Shdr *Header)
- : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {
+ : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {}
+
+template <class ELFT> void MergeInputSection<ELFT>::splitIntoPieces() {
ArrayRef<uint8_t> Data = this->getSectionData();
uintX_t EntSize = this->Header->sh_entsize;
if (this->Header->sh_flags & SHF_STRINGS)
this->Pieces = splitStrings(Data, EntSize);
else
this->Pieces = splitNonStrings(Data, EntSize);
+
+ if (Config->GcSections)
+ for (uintX_t Off : LiveOffsets)
+ this->getSectionPiece(Off)->Live = true;
}
template <class ELFT>
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=270455&r1=270454&r2=270455&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Mon May 23 11:55:43 2016
@@ -12,6 +12,7 @@
#include "Config.h"
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Object/ELF.h"
@@ -171,9 +172,17 @@ template <class ELFT> class MergeInputSe
public:
MergeInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
static bool classof(const InputSectionBase<ELFT> *S);
- // Translate an offset in the input section to an offset in the output
- // section.
+ void splitIntoPieces();
+
+ // Mark the piece at a given offset live. Used by GC.
+ void markLiveAt(uintX_t Offset) { LiveOffsets.insert(Offset); }
+
+ // Translate an offset in the input section to an offset
+ // in the output section.
uintX_t getOffset(uintX_t Offset);
+
+private:
+ llvm::DenseSet<uintX_t> LiveOffsets;
};
// This corresponds to a .eh_frame section of an input file.
Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=270455&r1=270454&r2=270455&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Mon May 23 11:55:43 2016
@@ -141,10 +141,13 @@ template <class ELFT> void elf::markLive
auto Enqueue = [&](ResolvedReloc<ELFT> R) {
if (!R.Sec)
return;
- if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec)) {
- SectionPiece *Piece = MS->getSectionPiece(R.Offset);
- Piece->Live = true;
- }
+
+ // Usually, a whole section is marked as live or dead, but in mergeable
+ // (splittable) sections, each piece of data has independent liveness bit.
+ // So we explicitly tell it which offset is in use.
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec))
+ MS->markLiveAt(R.Offset);
+
if (R.Sec->Live)
return;
R.Sec->Live = true;
More information about the llvm-commits
mailing list