diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -349,6 +349,9 @@ /// This attribute is only valid when hasCFG() == true. bool HasCanonicalCFG{true}; + /// True if another function body was merged into this one. + bool HasFunctionsFoldedInto{false}; + /// Name for the section this function code should reside in. std::string CodeSectionName; @@ -1407,6 +1410,9 @@ /// Return true if the body of the function was merged into another function. bool isFolded() const { return FoldedIntoFunction != nullptr; } + /// Return true if other functions were folded into this one. + bool hasFunctionsFoldedInto() const { return HasFunctionsFoldedInto; } + /// If this function was folded, return the function it was folded into. BinaryFunction *getFoldedIntoFunction() const { return FoldedIntoFunction; } @@ -1770,6 +1776,9 @@ void setFolded(BinaryFunction *BF) { FoldedIntoFunction = BF; } + /// Indicate that another function body was merged with this function. + void setHasFunctionsFoldedInto() { HasFunctionsFoldedInto = true; } + BinaryFunction &setPersonalityFunction(uint64_t Addr) { assert(!PersonalityFunction && "can't set personality function twice"); PersonalityFunction = BC.getOrCreateGlobalSymbol(Addr, "FUNCat"); diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1345,6 +1345,8 @@ ChildBF.setFolded(&ParentBF); } + + ParentBF.setHasFunctionsFoldedInto(); } void BinaryContext::fixBinaryDataHoles() { diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -413,7 +413,7 @@ uint64_t NumFunctionsFolded = 0; std::atomic NumJTFunctionsFolded{0}; std::atomic BytesSavedEstimate{0}; - std::atomic CallsSavedEstimate{0}; + std::atomic NumCalled{0}; std::atomic NumFoldedLastIteration{0}; CongruentBucketsMap CongruentBuckets; @@ -493,6 +493,8 @@ }); BinaryFunction *ParentBF = Twins[0]; + if (!ParentBF->hasFunctionsFoldedInto()) + NumCalled += ParentBF->getKnownExecutionCount(); for (unsigned I = 1; I < Twins.size(); ++I) { BinaryFunction *ChildBF = Twins[I]; LLVM_DEBUG(dbgs() << "BOLT-DEBUG: folding " << *ChildBF << " into " @@ -506,8 +508,8 @@ // Fold the function and remove from the list of processed functions. BytesSavedEstimate += ChildBF->getSize(); - CallsSavedEstimate += std::min(ChildBF->getKnownExecutionCount(), - ParentBF->getKnownExecutionCount()); + if (!ChildBF->hasFunctionsFoldedInto()) + NumCalled += ChildBF->getKnownExecutionCount(); BC.foldFunction(*ChildBF, *ParentBF); ++NumFoldedLastIteration; @@ -579,8 +581,8 @@ << " functions had jump tables.\n" << "BOLT-INFO: Removing all identical functions will save " << format("%.2lf", (double)BytesSavedEstimate / 1024) - << " KB of code space. Folded functions were called " - << CallsSavedEstimate << " times based on profile.\n"; + << " KB of code space. Folded functions were called " << NumCalled + << " times based on profile.\n"; } } // namespace bolt