@@ -223,6 +223,22 @@ static cl::opt<unsigned> TopCalledLimit(
223223 " functions section" ),
224224 cl::init(100 ), cl::Hidden, cl::cat(BoltCategory));
225225
226+ // Profile density options, synced with llvm-profgen/ProfileGenerator.cpp
227+ static cl::opt<bool > ShowDensity (" show-density" , cl::init(false ),
228+ cl::desc(" show profile density details" ),
229+ cl::Optional);
230+
231+ static cl::opt<int > ProfileDensityCutOffHot (
232+ " profile-density-cutoff-hot" , cl::init(990000 ),
233+ cl::desc(" Total samples cutoff for functions used to calculate "
234+ " profile density." ));
235+
236+ static cl::opt<double > ProfileDensityThreshold (
237+ " profile-density-threshold" , cl::init(0 ),
238+ cl::desc(" If the profile density is below the given threshold, it "
239+ " will be suggested to increase the sampling rate." ),
240+ cl::Optional);
241+
226242} // namespace opts
227243
228244namespace llvm {
@@ -1383,6 +1399,7 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) {
13831399 uint64_t StaleSampleCount = 0 ;
13841400 uint64_t InferredSampleCount = 0 ;
13851401 std::vector<const BinaryFunction *> ProfiledFunctions;
1402+ std::vector<std::pair<double , uint64_t >> FuncDensityList;
13861403 const char *StaleFuncsHeader = " BOLT-INFO: Functions with stale profile:\n " ;
13871404 for (auto &BFI : BC.getBinaryFunctions ()) {
13881405 const BinaryFunction &Function = BFI.second ;
@@ -1441,6 +1458,22 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) {
14411458 StaleSampleCount += SampleCount;
14421459 ++NumAllStaleFunctions;
14431460 }
1461+
1462+ if (opts::ShowDensity) {
1463+ uint64_t Size = Function.getSize ();
1464+ // In case of BOLT split functions registered in BAT, executed traces are
1465+ // automatically attributed to the main fragment. Add up function sizes
1466+ // for all fragments.
1467+ if (IsHotParentOfBOLTSplitFunction)
1468+ for (const BinaryFunction *Fragment : Function.getFragments ())
1469+ Size += Fragment->getSize ();
1470+ double Density = (double )1.0 * Function.getSampleCountInBytes () / Size;
1471+ FuncDensityList.emplace_back (Density, SampleCount);
1472+ LLVM_DEBUG (BC.outs () << Function << " : executed bytes "
1473+ << Function.getSampleCountInBytes () << " , size (b) "
1474+ << Size << " , density " << Density
1475+ << " , sample count " << SampleCount << ' \n ' );
1476+ }
14441477 }
14451478 BC.NumProfiledFuncs = ProfiledFunctions.size ();
14461479 BC.NumStaleProfileFuncs = NumStaleProfileFunctions;
@@ -1684,6 +1717,50 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) {
16841717 BC.outs () << " . Use -print-unknown to see the list." ;
16851718 BC.outs () << ' \n ' ;
16861719 }
1720+
1721+ if (opts::ShowDensity) {
1722+ double Density = 0.0 ;
1723+ // Sorted by the density in descending order.
1724+ llvm::stable_sort (FuncDensityList,
1725+ [&](const std::pair<double , uint64_t > &A,
1726+ const std::pair<double , uint64_t > &B) {
1727+ if (A.first != B.first )
1728+ return A.first > B.first ;
1729+ return A.second < B.second ;
1730+ });
1731+
1732+ uint64_t AccumulatedSamples = 0 ;
1733+ uint32_t I = 0 ;
1734+ assert (opts::ProfileDensityCutOffHot <= 1000000 &&
1735+ " The cutoff value is greater than 1000000(100%)" );
1736+ while (AccumulatedSamples <
1737+ TotalSampleCount *
1738+ static_cast <float >(opts::ProfileDensityCutOffHot) /
1739+ 1000000 &&
1740+ I < FuncDensityList.size ()) {
1741+ AccumulatedSamples += FuncDensityList[I].second ;
1742+ Density = FuncDensityList[I].first ;
1743+ I++;
1744+ }
1745+ if (Density == 0.0 ) {
1746+ BC.errs () << " BOLT-WARNING: the output profile is empty or the "
1747+ " --profile-density-cutoff-hot option is "
1748+ " set too low. Please check your command.\n " ;
1749+ } else if (Density < opts::ProfileDensityThreshold) {
1750+ BC.errs ()
1751+ << " BOLT-WARNING: BOLT is estimated to optimize better with "
1752+ << format (" %.1f" , opts::ProfileDensityThreshold / Density)
1753+ << " x more samples. Please consider increasing sampling rate or "
1754+ " profiling for longer duration to get more samples.\n " ;
1755+ }
1756+
1757+ BC.outs () << " BOLT-INFO: Functions with density >= "
1758+ << format (" %.1f" , Density) << " account for "
1759+ << format (" %.2f" ,
1760+ static_cast <double >(opts::ProfileDensityCutOffHot) /
1761+ 10000 )
1762+ << " % total sample counts.\n " ;
1763+ }
16871764 return Error::success ();
16881765}
16891766
0 commit comments