[COFF] Avoid allocating temporary vectors during ICF
Heap profiling with ETW shows that LLD performs 4,053,721 heap allocations over its lifetime, and ~800,000 of them come from assocEquals. These vectors are created just to do a comparison, so fuse the comparison into the loop and avoid the allocation. ICF is overall a small portion of the time spent linking, and I did not measure overall throughput improvements from this change above the noise threshold. However, these show up in the heap profiler, and the work is done, so we might as well land it if the code is clear enough. Reviewed By: hans Differential Revision: https://reviews.llvm.org/D79297
This commit is contained in:
parent
d1ff003fbb
commit
fce5457a14
|
|
@ -269,7 +269,8 @@ public:
|
||||||
AssociatedIterator() = default;
|
AssociatedIterator() = default;
|
||||||
AssociatedIterator(SectionChunk *head) : cur(head) {}
|
AssociatedIterator(SectionChunk *head) : cur(head) {}
|
||||||
bool operator==(const AssociatedIterator &r) const { return cur == r.cur; }
|
bool operator==(const AssociatedIterator &r) const { return cur == r.cur; }
|
||||||
const SectionChunk &operator*() const { return *cur; }
|
// FIXME: Wrong const-ness, but it makes filter ranges work.
|
||||||
|
SectionChunk &operator*() const { return *cur; }
|
||||||
SectionChunk &operator*() { return *cur; }
|
SectionChunk &operator*() { return *cur; }
|
||||||
AssociatedIterator &operator++() {
|
AssociatedIterator &operator++() {
|
||||||
cur = cur->assocChildren;
|
cur = cur->assocChildren;
|
||||||
|
|
|
||||||
|
|
@ -127,15 +127,19 @@ void ICF::segregate(size_t begin, size_t end, bool constant) {
|
||||||
|
|
||||||
// Returns true if two sections' associative children are equal.
|
// Returns true if two sections' associative children are equal.
|
||||||
bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) {
|
bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) {
|
||||||
auto childClasses = [&](const SectionChunk *sc) {
|
// Ignore associated metadata sections that don't participate in ICF, such as
|
||||||
std::vector<uint32_t> classes;
|
// debug info and CFGuard metadata.
|
||||||
for (const SectionChunk &c : sc->children())
|
auto considerForICF = [](const SectionChunk &assoc) {
|
||||||
if (!c.getSectionName().startswith(".debug") &&
|
StringRef Name = assoc.getSectionName();
|
||||||
c.getSectionName() != ".gfids$y" && c.getSectionName() != ".gljmp$y")
|
return !(Name.startswith(".debug") || Name == ".gfids$y" ||
|
||||||
classes.push_back(c.eqClass[cnt % 2]);
|
Name == ".gljmp$y");
|
||||||
return classes;
|
|
||||||
};
|
};
|
||||||
return childClasses(a) == childClasses(b);
|
auto ra = make_filter_range(a->children(), considerForICF);
|
||||||
|
auto rb = make_filter_range(b->children(), considerForICF);
|
||||||
|
return std::equal(ra.begin(), ra.end(), rb.begin(), rb.end(),
|
||||||
|
[&](const SectionChunk &ia, const SectionChunk &ib) {
|
||||||
|
return ia.eqClass[cnt % 2] == ib.eqClass[cnt % 2];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare "non-moving" part of two sections, namely everything
|
// Compare "non-moving" part of two sections, namely everything
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue