diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -15,6 +15,7 @@ #include "lld/Common/CommonLinkerContext.h" #include "llvm/Support/Parallel.h" #include "llvm/Support/TimeProfiler.h" +#include "llvm/Support/xxhash.h" #include @@ -361,7 +362,8 @@ for (ConcatInputSection *isec : inputSections) { // FIXME: consider non-code __text sections as hashable? bool isHashable = (isCodeSection(isec) || isCfStringSection(isec)) && - !isec->shouldOmitFromOutput() && isec->isHashableForICF(); + !isec->shouldOmitFromOutput() && + sectionType(isec->getFlags()) == MachO::S_REGULAR; if (isHashable) { hashable.push_back(isec); for (Defined *d : isec->symbols) @@ -371,8 +373,12 @@ isec->icfEqClass[0] = ++icfUniqueID; } } - parallelForEach(hashable, - [](ConcatInputSection *isec) { isec->hashForICF(); }); + parallelForEach(hashable, [](ConcatInputSection *isec) { + assert(isec->icfEqClass[0] == 0); // don't overwrite a unique ID! + // Turn-on the top bit to guarantee that valid hashes have no collisions + // with the small-integer unique IDs for ICF-ineligible sections + isec->icfEqClass[0] = xxHash64(isec->data) | (1ull << 63); + }); // Now that every input section is either hashed or marked as unique, run the // segregation algorithm to detect foldable subsections. ICF(hashable).run(); diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -100,8 +100,6 @@ void markLive(uint64_t off) override { live = true; } bool isCoalescedWeak() const { return wasCoalesced && symbols.empty(); } bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); } - bool isHashableForICF() const; - void hashForICF(); void writeTo(uint8_t *buf); void foldIdentical(ConcatInputSection *redundant); diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -77,48 +77,6 @@ .str(); } -// ICF needs to hash any section that might potentially be duplicated so -// that it can match on content rather than identity. -bool ConcatInputSection::isHashableForICF() const { - switch (sectionType(getFlags())) { - case S_REGULAR: - return true; - case S_CSTRING_LITERALS: - case S_4BYTE_LITERALS: - case S_8BYTE_LITERALS: - case S_16BYTE_LITERALS: - case S_LITERAL_POINTERS: - llvm_unreachable("found unexpected literal type in ConcatInputSection"); - case S_ZEROFILL: - case S_GB_ZEROFILL: - case S_NON_LAZY_SYMBOL_POINTERS: - case S_LAZY_SYMBOL_POINTERS: - case S_SYMBOL_STUBS: - case S_MOD_INIT_FUNC_POINTERS: - case S_MOD_TERM_FUNC_POINTERS: - case S_COALESCED: - case S_INTERPOSING: - case S_DTRACE_DOF: - case S_LAZY_DYLIB_SYMBOL_POINTERS: - case S_THREAD_LOCAL_REGULAR: - case S_THREAD_LOCAL_ZEROFILL: - case S_THREAD_LOCAL_VARIABLES: - case S_THREAD_LOCAL_VARIABLE_POINTERS: - case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: - return false; - default: - llvm_unreachable("Section type"); - } -} - -void ConcatInputSection::hashForICF() { - assert(data.data()); // zeroFill section data has nullptr with non-zero size - assert(icfEqClass[0] == 0); // don't overwrite a unique ID! - // Turn-on the top bit to guarantee that valid hashes have no collisions - // with the small-integer unique IDs for ICF-ineligible sections - icfEqClass[0] = xxHash64(data) | (1ull << 63); -} - void ConcatInputSection::foldIdentical(ConcatInputSection *copy) { align = std::max(align, copy->align); copy->live = false;