This mirrors the code organization in `lld/ELF`.
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D120378
#include "lld/Common/CommonLinkerContext.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/xxhash.h"
#include <atomic>
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)
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();
.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;
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);