Lines Matching +full:coexist +full:- +full:support

1 //===- ICF.cpp ------------------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
18 #include "llvm/Support/LEB128.h"
19 #include "llvm/Support/Parallel.h"
20 #include "llvm/Support/TimeProfiler.h"
21 #include "llvm/Support/xxhash.h"
49 // ICF needs a copy of the inputs vector because its equivalence-class
84 // The __DATA segment is read/write at the MMU, and as application-writeable
90 // FIXME(gkm): implement keep-unique attributes
91 // FIXME(gkm): implement address-significance tables for MachO object files
93 // Compare "non-moving" parts of two ConcatInputSections, namely everything
100 if (ia->parent != ib->parent)
102 if (ia->data.size() != ib->data.size())
104 if (ia->data != ib->data)
106 if (ia->relocs.size() != ib->relocs.size())
127 if (sa->kind() != sb->kind())
136 if (!da->isec() || !db->isec()) {
137 assert(da->isAbsolute() && db->isAbsolute());
138 return da->value + ra.addend == db->value + rb.addend;
140 isecA = da->isec();
141 valueA = da->value;
142 isecB = db->isec();
143 valueB = db->value;
149 if (isecA->parent != isecB->parent)
152 assert(isecA->kind() == isecB->kind());
162 return isecA->getOffset(valueA) == isecB->getOffset(valueB) &&
167 return isecA->getOffset(ra.addend) == isecB->getOffset(rb.addend);
170 return std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(),
174 // Compare the "moving" parts of two ConcatInputSections -- i.e. everything not
180 assert(ia->relocs.size() == ib->relocs.size());
188 // identical-referent check above. Non-matching DylibSymbols were filtered
192 if (da->isAbsolute())
194 isecA = dyn_cast<ConcatInputSection>(da->isec());
197 isecB = cast<ConcatInputSection>(db->isec());
206 return isecA->icfEqClass[icfPass % 2] == isecB->icfEqClass[icfPass % 2];
208 if (!std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(), f))
215 auto hasUnwind = [](Defined *d) { return d->unwindEntry() != nullptr; };
216 const auto *itA = llvm::find_if(ia->symbols, hasUnwind);
217 const auto *itB = llvm::find_if(ib->symbols, hasUnwind);
218 if (itA == ia->symbols.end())
219 return itB == ib->symbols.end();
220 if (itB == ib->symbols.end())
224 if (da->unwindEntry()->icfEqClass[icfPass % 2] !=
225 db->unwindEntry()->icfEqClass[icfPass % 2] ||
226 da->value != 0 || db->value != 0)
228 auto isZero = [](Defined *d) { return d->value == 0; };
229 return std::find_if_not(std::next(itA), ia->symbols.end(), isZero) ==
230 ia->symbols.end() &&
231 std::find_if_not(std::next(itB), ib->symbols.end(), isZero) ==
232 ib->symbols.end();
237 uint64_t beginHash = icfInputs[begin]->icfEqClass[icfPass % 2];
239 if (beginHash != icfInputs[i]->icfEqClass[icfPass % 2])
265 // Shard into non-overlapping intervals, and call FUNC in parallel. The
274 boundaries[i] = findBoundary((i - 1) * step, icfInputs.size());
277 if (boundaries[i - 1] < boundaries[i]) {
278 forEachClassRange(boundaries[i - 1], boundaries[i], func);
285 // Into each origin-section hash, combine all reloc referent section hashes.
288 uint32_t hash = isec->icfEqClass[icfPass % 2];
289 for (const Reloc &r : isec->relocs) {
292 if (defined->isec()) {
294 dyn_cast<ConcatInputSection>(defined->isec()))
295 hash += defined->value + referentIsec->icfEqClass[icfPass % 2];
297 hash += defined->isec()->kind() +
298 defined->isec()->getOffset(defined->value);
300 hash += defined->value;
308 // Set MSB to 1 to avoid collisions with non-hashed classes.
309 isec->icfEqClass[(icfPass + 1) % 2] = hash | (1ull << 31);
315 return a->icfEqClass[0] < b->icfEqClass[0];
336 if (end - begin < 2)
340 beginIsec->foldIdentical(icfInputs[i]);
352 return (this->*equals)(icfInputs[begin], isec);
354 size_t mid = bound - icfInputs.begin();
359 icfInputs[i]->icfEqClass[(icfPass + 1) % 2] = mid;
371 if (d->isec())
372 d->isec()->keepUnique = true;
382 Section *addrSigSection = obj->addrSigSection;
385 assert(addrSigSection->subsections.size() == 1);
387 const InputSection *isec = addrSigSection->subsections[0].isec;
389 for (const Reloc &r : isec->relocs) {
400 // The ICF equivalence-class segregation algorithm relies on pre-computed
408 // it into an unfoldable singleton equivalence class. Begin the unique-ID
410 // equivalence-class IDs which begin at 0. Since hashes & unique IDs never
411 // coexist with equivalence-class IDs, this is not necessary, but might help
423 sectionType(isec->getFlags()) == MachO::S_REGULAR);
424 // FIXME: consider non-code __text sections as foldable?
428 !isec->keepUnique && !isec->hasAltEntry &&
429 !isec->shouldOmitFromOutput() && hasFoldableFlags;
432 for (Defined *d : isec->symbols)
433 if (d->unwindEntry())
434 foldable.push_back(d->unwindEntry());
443 // thread-safe. FIXME: Make a thread-safe allocator.
444 MutableArrayRef<uint8_t> copy = isec->data.copy(bAlloc());
445 for (const Reloc &r : isec->relocs)
446 target->relocateOne(copy.data() + r.offset, r, /*va=*/0,
448 isec->data = copy;
453 isec->icfEqClass[0] = ++icfUniqueID;
457 assert(isec->icfEqClass[0] == 0); // don't overwrite a unique ID!
458 // Turn-on the top bit to guarantee that valid hashes have no collisions
459 // with the small-integer unique IDs for ICF-ineligible sections
460 isec->icfEqClass[0] = xxh3_64bits(isec->data) | (1ull << 31);