diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 4637fe311927..80375b1167b0 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -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. diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index 1c99a60bfaad..e412bc153021 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -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) { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index bde326aee261..4539b7221cb5 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -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 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();