[lld] [lld-macho] Fix branch extension thunk estimation logic (PR #120529)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 19 09:53:39 PST 2024
https://github.com/alx32 updated https://github.com/llvm/llvm-project/pull/120529
>From fe6369ae90d7a69dc013781678b54b6ac39ea9d0 Mon Sep 17 00:00:00 2001
From: Alex B <alexborcan at meta.com>
Date: Wed, 18 Dec 2024 23:37:48 -0800
Subject: [PATCH 1/2] [lld-macho] Fix branch extension thunk estimation logic
---
lld/MachO/ConcatOutputSection.cpp | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp
index 6a9301f84a03ef..9610a80e309bac 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -184,6 +184,15 @@ uint64_t TextOutputSection::estimateStubsInRangeVA(size_t callIdx) const {
InputSection *isec = inputs[i];
isecEnd = alignToPowerOf2(isecEnd, isec->align) + isec->getSize();
}
+
+ // Tally up any thunks that have already been placed that have address higher
+ // than the equivalent callIdx. We first find the index of the first thunk
+ // that is beyond the current inputs[callIdx].
+ auto itPostcallIdxThunks = std::partition_point(
+ thunks.begin(), thunks.end(),
+ [isecVA](const ConcatInputSection *t) { return t->getVA() <= isecVA; });
+ uint32_t existingForwardThunks = thunks.end() - itPostcallIdxThunks;
+
// Estimate the address after which call sites can safely call stubs
// directly rather than through intermediary thunks.
uint64_t forwardBranchRange = target->forwardBranchRange;
@@ -191,8 +200,21 @@ uint64_t TextOutputSection::estimateStubsInRangeVA(size_t callIdx) const {
"should not run thunk insertion if all code fits in jump range");
assert(isecEnd - isecVA <= forwardBranchRange &&
"should only finalize sections in jump range");
- uint64_t stubsInRangeVA = isecEnd + maxPotentialThunks * target->thunkSize +
- in.stubs->getSize() - forwardBranchRange;
+
+ // Estimate the maximum size of the code, right before the stubs section
+ uint32_t maxTextSize = 0;
+ // Add the size of all the inputs, including the unprocessed ones.
+ maxTextSize += isecEnd;
+
+ // Add the size of the thunks that may be created in the future
+ maxTextSize += maxPotentialThunks * target->thunkSize;
+
+ // Add the size of the thunks that have already been created that are ahead
+ maxTextSize += existingForwardThunks * target->thunkSize;
+
+ uint64_t stubsInRangeVA =
+ maxTextSize + in.stubs->getSize() - forwardBranchRange;
+
log("thunks = " + std::to_string(thunkMap.size()) +
", potential = " + std::to_string(maxPotentialThunks) +
", stubs = " + std::to_string(in.stubs->getSize()) + ", isecVA = " +
>From bc5e3426d0f71a2fc364258a4009b3848f856d95 Mon Sep 17 00:00:00 2001
From: Alex B <alexborcan at meta.com>
Date: Thu, 19 Dec 2024 09:53:27 -0800
Subject: [PATCH 2/2] uint32 => uint64 + extra comments
---
lld/MachO/ConcatOutputSection.cpp | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp
index 9610a80e309bac..cf3ab72c351e4c 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -191,7 +191,7 @@ uint64_t TextOutputSection::estimateStubsInRangeVA(size_t callIdx) const {
auto itPostcallIdxThunks = std::partition_point(
thunks.begin(), thunks.end(),
[isecVA](const ConcatInputSection *t) { return t->getVA() <= isecVA; });
- uint32_t existingForwardThunks = thunks.end() - itPostcallIdxThunks;
+ uint64_t existingForwardThunks = thunks.end() - itPostcallIdxThunks;
// Estimate the address after which call sites can safely call stubs
// directly rather than through intermediary thunks.
@@ -201,26 +201,30 @@ uint64_t TextOutputSection::estimateStubsInRangeVA(size_t callIdx) const {
assert(isecEnd - isecVA <= forwardBranchRange &&
"should only finalize sections in jump range");
- // Estimate the maximum size of the code, right before the stubs section
- uint32_t maxTextSize = 0;
+ // Estimate the maximum size of the code, right before the stubs section.
+ uint64_t maxTextSize = 0;
// Add the size of all the inputs, including the unprocessed ones.
maxTextSize += isecEnd;
- // Add the size of the thunks that may be created in the future
+ // Add the size of the thunks that may be created in the future. Since
+ // 'maxPotentialThunks' overcounts, this is an estimate of the upper limit.
maxTextSize += maxPotentialThunks * target->thunkSize;
// Add the size of the thunks that have already been created that are ahead
maxTextSize += existingForwardThunks * target->thunkSize;
- uint64_t stubsInRangeVA =
- maxTextSize + in.stubs->getSize() - forwardBranchRange;
+ // Estimated maximum VA of last stub.
+ uint64_t maxVAOfLastStub = maxTextSize + in.stubs->getSize();
+
+ // Calculaate the first address that is gueranteed to not need a thunk to
+ // reach any stub.git
+ uint64_t stubsInRangeVA = maxVAOfLastStub - forwardBranchRange;
log("thunks = " + std::to_string(thunkMap.size()) +
- ", potential = " + std::to_string(maxPotentialThunks) +
- ", stubs = " + std::to_string(in.stubs->getSize()) + ", isecVA = " +
- utohexstr(isecVA) + ", threshold = " + utohexstr(stubsInRangeVA) +
- ", isecEnd = " + utohexstr(isecEnd) +
- ", tail = " + utohexstr(isecEnd - isecVA) +
+ ", potential = " + std::to_string(maxPotentialThunks) + ", stubs = " +
+ std::to_string(in.stubs->getSize()) + ", isecVA = " + utohexstr(isecVA) +
+ ", threshold = " + utohexstr(stubsInRangeVA) + ", isecEnd = " +
+ utohexstr(isecEnd) + ", tail = " + utohexstr(isecEnd - isecVA) +
", slop = " + utohexstr(forwardBranchRange - (isecEnd - isecVA)));
return stubsInRangeVA;
}
More information about the llvm-commits
mailing list