[BOLT] Make FoldedIntoFunction always point to root parent (#180855)

After ICF folds functions, FoldedIntoFunction may point to a function
that was also folded. Add a post-processing step at the end of ICF to
flatten all chains so FoldedIntoFunction always points to the ultimate
root parent (a function that is not itself folded).
This commit is contained in:
Maksim Panchenko 2026-02-11 11:35:02 -08:00 committed by GitHub
parent 2fd5479f2c
commit 5129b3c449
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 8 deletions

View File

@ -400,7 +400,8 @@ private:
FragmentsSetTy ParentFragments;
/// Indicate if the function body was folded into another function.
/// Used by ICF optimization.
/// Used by ICF optimization. Always points to the root parent function
/// (i.e., a function that is not itself folded).
BinaryFunction *FoldedIntoFunction{nullptr};
/// All fragments for a parent function.

View File

@ -605,6 +605,19 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
} while (NumFoldedLastIteration > 0);
// Flatten folded function chains so FoldedIntoFunction always points
// to the root parent.
for (auto &BFI : BC.getBinaryFunctions()) {
BinaryFunction &BF = BFI.second;
if (!BF.isFolded())
continue;
BinaryFunction *Parent = BF.getFoldedIntoFunction();
while (Parent->isFolded())
Parent = Parent->getFoldedIntoFunction();
if (Parent != BF.getFoldedIntoFunction())
BF.setFolded(Parent);
}
LLVM_DEBUG({
// Print functions that are congruent but not identical.
for (auto &CBI : CongruentBuckets) {

View File

@ -5162,9 +5162,7 @@ void RewriteInstance::updateELFSymbolTable(
auto addExtraSymbols = [&](const BinaryFunction &Function,
const ELFSymTy &FunctionSymbol) {
if (Function.isFolded()) {
BinaryFunction *ICFParent = Function.getFoldedIntoFunction();
while (ICFParent->isFolded())
ICFParent = ICFParent->getFoldedIntoFunction();
const BinaryFunction *ICFParent = Function.getFoldedIntoFunction();
ELFSymTy ICFSymbol = FunctionSymbol;
SmallVector<char, 256> Buf;
ICFSymbol.st_name =
@ -5280,8 +5278,7 @@ void RewriteInstance::updateELFSymbolTable(
// instead so that the symbol gets updated to the parent's output address.
// In non-relocation mode, folded functions are emitted at their original
// location, so we keep the original function reference.
// Follow the chain of folded functions to get the final parent.
while (BC->HasRelocations && Function && Function->isFolded())
if (BC->HasRelocations && Function && Function->isFolded())
Function = Function->getFoldedIntoFunction();
// Ignore false function references, e.g. when the section address matches
// the address of the function.
@ -6084,8 +6081,8 @@ uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {
return 0;
// If this function was folded, its output address is 0 since it wasn't
// emitted. Follow the chain to get the parent function's address.
while (Function->isFolded())
// emitted. Get the parent function's address.
if (Function->isFolded())
Function = Function->getFoldedIntoFunction();
return Function->getOutputAddress();