[lld] [lld-macho][arm64] Enhance safe ICF with thunk-based deduplication (PR #106573)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 30 17:22:17 PDT 2024
================
@@ -251,6 +252,63 @@ void ICF::forEachClassRange(size_t begin, size_t end,
}
}
+// Given a range of identical icfInputs's, replace address significant functions
+// with a thunk that is just a direct branch to the first function in the
+// series. This way we end up we keep only one main body of the function but we
+// still retain address uniqueness of rellevant functions by having them be a
+// direct branch thunk rather than contain a full copy of the actual function
+// body.
+void ICF::applySafeThunksToRange(size_t begin, size_t end) {
+ // If we need to create a unique ICF thunk, use the first section as the
+ // section that all thunks will branch to.
+ ConcatInputSection *masterIsec = icfInputs[begin];
+ uint32_t thunkSize = target->getICFSafeThunkSize();
+ static std::mutex thunkInsertionMutex;
+
+ uint32_t keepUniqueCount = masterIsec->keepUnique ? 1 : 0;
+ for (size_t i = begin + 1; i < end; ++i) {
+ ConcatInputSection *isec = icfInputs[i];
+ if (isec->keepUnique)
+ ++keepUniqueCount;
+
+ // We create thunks for the 2nd, 3rd, ... keepUnique sections. The first
+ // keepUnique section we leave as is - as it will not end up sharing an
+ // address with any other keepUnique section.
+ if (keepUniqueCount >= 2 && isec->keepUnique) {
+ // If the target to be folded is smaller than the thunk size, then just
+ // leave it as-is - creating the thunk would be a net loss.
+ if (isec->data.size() <= thunkSize)
+ return;
+
+ // applySafeThunksToRange is called from multiple threads, but
+ // `makeSyntheticInputSection` and `addInputSection` are not thread safe.
+ // So we need to guard them with a mutex.
+ ConcatInputSection *thunk;
+ {
+ std::lock_guard<std::mutex> lock(thunkInsertionMutex);
+ thunk = makeSyntheticInputSection(isec->getSegName(), isec->getName());
+ addInputSection(thunk);
+ }
+
+ target->initICFSafeThunkBody(thunk, masterIsec);
+ thunk->foldIdentical(isec);
+
+ // Since we're folding the target function into a thunk, we need to adjust
+ // the symbols that now got relocated from the target function to the
+ // thunk.
+ // Since the thunk is only one branch, we move all symbols to offset 0 and
+ // make sure that the size of all non-zero-size symbols is equal to the
+ // size of the branch.
+ for (auto *sym : isec->symbols) {
+ if (sym->value != 0)
----------------
alx32 wrote:
value yes, but if symbol is 0-size we should leave it be 0-size.
https://github.com/llvm/llvm-project/pull/106573
More information about the llvm-commits
mailing list