Skip to content

Commit 343e822

Browse files
author
George Rimar
committedNov 4, 2017
[ELF] - Stop using SectionKey for creating output sections.
Stop using SectionKey for creating output sections. Initially SectionKey was designed because we merged section with use of Flags and Alignment fields. Currently LLD merges them by name only, except the case when -relocatable output is produced. In that case we still merge sections only with the same flags and alignment. There is probably no issue at all to stop using Flags and Alignment for -r and just disable the merging in that case. After doing that change we can get rid of using SectionKey. That is not only simplifies the code, but also gives some perfomance boost. I tried to link chrome and mozilla, results are next: * chrome link time goes from 1,666750355s to 1,551585364s, that is about 7%. * mozilla time changes from 3,210261947 to 3,153782940, or about 2%. Differential revision: https://reviews.llvm.org/D39594 llvm-svn: 317406
1 parent ddd2424 commit 343e822

File tree

2 files changed

+50
-91
lines changed

2 files changed

+50
-91
lines changed
 

‎lld/ELF/OutputSections.cpp

+49-75
Original file line numberDiff line numberDiff line change
@@ -142,61 +142,6 @@ void OutputSection::addSection(InputSection *IS) {
142142
}
143143
}
144144

145-
static SectionKey createKey(InputSectionBase *IS, StringRef OutsecName) {
146-
// When control reaches here, mergeable sections have already been
147-
// merged except the -r case. If that's the case, we want to combine
148-
// mergeable sections by sh_entsize and sh_flags.
149-
if (Config->Relocatable && (IS->Flags & SHF_MERGE)) {
150-
uint64_t Flags = IS->Flags & (SHF_MERGE | SHF_STRINGS);
151-
uint32_t Alignment = std::max<uint32_t>(IS->Alignment, IS->Entsize);
152-
return SectionKey{OutsecName, Flags, Alignment};
153-
}
154-
155-
// The ELF spec just says
156-
// ----------------------------------------------------------------
157-
// In the first phase, input sections that match in name, type and
158-
// attribute flags should be concatenated into single sections.
159-
// ----------------------------------------------------------------
160-
//
161-
// However, it is clear that at least some flags have to be ignored for
162-
// section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be
163-
// ignored. We should not have two output .text sections just because one was
164-
// in a group and another was not for example.
165-
//
166-
// It also seems that that wording was a late addition and didn't get the
167-
// necessary scrutiny.
168-
//
169-
// Merging sections with different flags is expected by some users. One
170-
// reason is that if one file has
171-
//
172-
// int *const bar __attribute__((section(".foo"))) = (int *)0;
173-
//
174-
// gcc with -fPIC will produce a read only .foo section. But if another
175-
// file has
176-
//
177-
// int zed;
178-
// int *const bar __attribute__((section(".foo"))) = (int *)&zed;
179-
//
180-
// gcc with -fPIC will produce a read write section.
181-
//
182-
// Last but not least, when using linker script the merge rules are forced by
183-
// the script. Unfortunately, linker scripts are name based. This means that
184-
// expressions like *(.foo*) can refer to multiple input sections with
185-
// different flags. We cannot put them in different output sections or we
186-
// would produce wrong results for
187-
//
188-
// start = .; *(.foo.*) end = .; *(.bar)
189-
//
190-
// and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
191-
// another. The problem is that there is no way to layout those output
192-
// sections such that the .foo sections are the only thing between the start
193-
// and end symbols.
194-
//
195-
// Given the above issues, we instead merge sections by name and error on
196-
// incompatible types and flags.
197-
return SectionKey{OutsecName, 0, 0};
198-
}
199-
200145
OutputSectionFactory::OutputSectionFactory() {}
201146

202147
void elf::sortByOrder(MutableArrayRef<InputSection *> In,
@@ -252,8 +197,55 @@ OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS,
252197
return Out->RelocationSection;
253198
}
254199

255-
SectionKey Key = createKey(IS, OutsecName);
256-
OutputSection *&Sec = Map[Key];
200+
// When control reaches here, mergeable sections have already been
201+
// merged except the -r case. If that's the case, we do not combine them
202+
// and let final link to handle this optimization.
203+
if (Config->Relocatable && (IS->Flags & SHF_MERGE))
204+
return createSection(IS, OutsecName);
205+
206+
// The ELF spec just says
207+
// ----------------------------------------------------------------
208+
// In the first phase, input sections that match in name, type and
209+
// attribute flags should be concatenated into single sections.
210+
// ----------------------------------------------------------------
211+
//
212+
// However, it is clear that at least some flags have to be ignored for
213+
// section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be
214+
// ignored. We should not have two output .text sections just because one was
215+
// in a group and another was not for example.
216+
//
217+
// It also seems that that wording was a late addition and didn't get the
218+
// necessary scrutiny.
219+
//
220+
// Merging sections with different flags is expected by some users. One
221+
// reason is that if one file has
222+
//
223+
// int *const bar __attribute__((section(".foo"))) = (int *)0;
224+
//
225+
// gcc with -fPIC will produce a read only .foo section. But if another
226+
// file has
227+
//
228+
// int zed;
229+
// int *const bar __attribute__((section(".foo"))) = (int *)&zed;
230+
//
231+
// gcc with -fPIC will produce a read write section.
232+
//
233+
// Last but not least, when using linker script the merge rules are forced by
234+
// the script. Unfortunately, linker scripts are name based. This means that
235+
// expressions like *(.foo*) can refer to multiple input sections with
236+
// different flags. We cannot put them in different output sections or we
237+
// would produce wrong results for
238+
//
239+
// start = .; *(.foo.*) end = .; *(.bar)
240+
//
241+
// and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
242+
// another. The problem is that there is no way to layout those output
243+
// sections such that the .foo sections are the only thing between the start
244+
// and end symbols.
245+
//
246+
// Given the above issues, we instead merge sections by name and error on
247+
// incompatible types and flags.
248+
OutputSection *&Sec = Map[OutsecName];
257249
if (Sec) {
258250
Sec->addSection(cast<InputSection>(IS));
259251
return nullptr;
@@ -265,24 +257,6 @@ OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS,
265257

266258
OutputSectionFactory::~OutputSectionFactory() {}
267259

268-
SectionKey DenseMapInfo<SectionKey>::getEmptyKey() {
269-
return SectionKey{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0};
270-
}
271-
272-
SectionKey DenseMapInfo<SectionKey>::getTombstoneKey() {
273-
return SectionKey{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0};
274-
}
275-
276-
unsigned DenseMapInfo<SectionKey>::getHashValue(const SectionKey &Val) {
277-
return hash_combine(Val.Name, Val.Flags, Val.Alignment);
278-
}
279-
280-
bool DenseMapInfo<SectionKey>::isEqual(const SectionKey &LHS,
281-
const SectionKey &RHS) {
282-
return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
283-
LHS.Flags == RHS.Flags && LHS.Alignment == RHS.Alignment;
284-
}
285-
286260
uint64_t elf::getHeaderSize() {
287261
if (Config->OFormatBinary)
288262
return 0;

‎lld/ELF/OutputSections.h

+1-16
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,9 @@ struct Out {
131131
static OutputSection *FiniArray;
132132
};
133133

134-
struct SectionKey {
135-
StringRef Name;
136-
uint64_t Flags;
137-
uint32_t Alignment;
138-
};
139134
} // namespace elf
140135
} // namespace lld
141136

142-
namespace llvm {
143-
template <> struct DenseMapInfo<lld::elf::SectionKey> {
144-
static lld::elf::SectionKey getEmptyKey();
145-
static lld::elf::SectionKey getTombstoneKey();
146-
static unsigned getHashValue(const lld::elf::SectionKey &Val);
147-
static bool isEqual(const lld::elf::SectionKey &LHS,
148-
const lld::elf::SectionKey &RHS);
149-
};
150-
} // namespace llvm
151-
152137
namespace lld {
153138
namespace elf {
154139
// This class knows how to create an output section for a given
@@ -163,7 +148,7 @@ class OutputSectionFactory {
163148
OutputSection *addInputSec(InputSectionBase *IS, StringRef OutsecName);
164149

165150
private:
166-
llvm::SmallDenseMap<SectionKey, OutputSection *> Map;
151+
llvm::StringMap<OutputSection *> Map;
167152
};
168153

169154
uint64_t getHeaderSize();

0 commit comments

Comments
 (0)
Please sign in to comment.