aboutsummaryrefslogtreecommitdiff
path: root/COFF/ICF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/ICF.cpp')
-rw-r--r--COFF/ICF.cpp27
1 files changed, 21 insertions, 6 deletions
diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp
index 7feb3c4e0b0c..34ea360fa925 100644
--- a/COFF/ICF.cpp
+++ b/COFF/ICF.cpp
@@ -22,6 +22,7 @@
#include "Chunks.h"
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Threads.h"
#include "lld/Common/Timer.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/Debug.h"
@@ -80,7 +81,7 @@ private:
bool ICF::isEligible(SectionChunk *C) {
// Non-comdat chunks, dead chunks, and writable chunks are not elegible.
bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
- if (!C->isCOMDAT() || !C->isLive() || Writable)
+ if (!C->isCOMDAT() || !C->Live || Writable)
return false;
// Code sections are eligible.
@@ -93,7 +94,11 @@ bool ICF::isEligible(SectionChunk *C) {
return true;
// So are vtables.
- return C->Sym && C->Sym->getName().startswith("??_7");
+ if (C->Sym && C->Sym->getName().startswith("??_7"))
+ return true;
+
+ // Anything else not in an address-significance table is eligible.
+ return !C->KeepUnique;
}
// Split an equivalence class into smaller classes.
@@ -222,10 +227,10 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
size_t Boundaries[NumShards + 1];
Boundaries[0] = 0;
Boundaries[NumShards] = Chunks.size();
- for_each_n(parallel::par, size_t(1), NumShards, [&](size_t I) {
+ parallelForEachN(1, NumShards, [&](size_t I) {
Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size());
});
- for_each_n(parallel::par, size_t(1), NumShards + 1, [&](size_t I) {
+ parallelForEachN(1, NumShards + 1, [&](size_t I) {
if (Boundaries[I - 1] < Boundaries[I]) {
forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
}
@@ -257,9 +262,19 @@ void ICF::run(ArrayRef<Chunk *> Vec) {
SC->Class[0] = NextId++;
// Initially, we use hash values to partition sections.
- for_each(parallel::par, Chunks.begin(), Chunks.end(), [&](SectionChunk *SC) {
+ parallelForEach(Chunks, [&](SectionChunk *SC) {
+ SC->Class[1] = xxHash64(SC->getContents());
+ });
+
+ // Combine the hashes of the sections referenced by each section into its
+ // hash.
+ parallelForEach(Chunks, [&](SectionChunk *SC) {
+ uint32_t Hash = SC->Class[1];
+ for (Symbol *B : SC->symbols())
+ if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B))
+ Hash ^= Sym->getChunk()->Class[1];
// Set MSB to 1 to avoid collisions with non-hash classs.
- SC->Class[0] = xxHash64(SC->getContents()) | (1 << 31);
+ SC->Class[0] = Hash | (1U << 31);
});
// From now on, sections in Chunks are ordered so that sections in