@@ -164,6 +164,10 @@ void DataAggregator::findPerfExecutable() {
164164void DataAggregator::start () {
165165 outs () << " PERF2BOLT: Starting data aggregation job for " << Filename << " \n " ;
166166
167+ // Turn on heatmap building if requested by --heatmap flag.
168+ if (!opts::HeatmapMode && opts::HeatmapOutput.getNumOccurrences ())
169+ opts::HeatmapMode = opts::HeatmapModeKind::HM_Optional;
170+
167171 // Don't launch perf for pre-aggregated files or when perf input is specified
168172 // by the user.
169173 if (opts::ReadPreAggregated || !opts::ReadPerfEvents.empty ())
@@ -502,24 +506,25 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
502506 errs () << " PERF2BOLT: failed to parse samples\n " ;
503507
504508 // Special handling for memory events
505- if (prepareToParse (" mem events" , MemEventsPPI, MemEventsErrorCallback))
506- return Error::success ();
507-
508- if (const std::error_code EC = parseMemEvents ())
509- errs () << " PERF2BOLT: failed to parse memory events: " << EC.message ()
510- << ' \n ' ;
509+ if (!prepareToParse (" mem events" , MemEventsPPI, MemEventsErrorCallback))
510+ if (const std::error_code EC = parseMemEvents ())
511+ errs () << " PERF2BOLT: failed to parse memory events: " << EC.message ()
512+ << ' \n ' ;
511513
512514 deleteTempFiles ();
513515
514516heatmap:
515- if (opts::HeatmapMode) {
516- if (std::error_code EC = printLBRHeatMap ()) {
517- errs () << " ERROR: failed to print heat map: " << EC.message () << ' \n ' ;
518- exit (1 );
519- }
520- exit (0 );
521- }
522- return Error::success ();
517+ if (!opts::HeatmapMode)
518+ return Error::success ();
519+
520+ if (std::error_code EC = printLBRHeatMap ())
521+ return errorCodeToError (EC);
522+
523+ if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Optional)
524+ return Error::success ();
525+
526+ assert (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive);
527+ exit (0 );
523528}
524529
525530Error DataAggregator::readProfile (BinaryContext &BC) {
@@ -635,8 +640,6 @@ bool DataAggregator::doBasicSample(BinaryFunction &OrigFunc, uint64_t Address,
635640
636641 BinaryFunction *ParentFunc = getBATParentFunction (OrigFunc);
637642 BinaryFunction &Func = ParentFunc ? *ParentFunc : OrigFunc;
638- if (ParentFunc || (BAT && !BAT->isBATFunction (Func.getAddress ())))
639- NumColdSamples += Count;
640643 // Attach executed bytes to parent function in case of cold fragment.
641644 Func.SampleCountInBytes += Count * BlockSize;
642645
@@ -740,15 +743,10 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
740743 if (BAT)
741744 Addr = BAT->translate (Func->getAddress (), Addr, IsFrom);
742745
743- BinaryFunction *ParentFunc = getBATParentFunction (*Func);
744- if (IsFrom &&
745- (ParentFunc || (BAT && !BAT->isBATFunction (Func->getAddress ()))))
746- NumColdSamples += Count;
747-
748- if (!ParentFunc)
749- return std::pair{Func, IsRet};
746+ if (BinaryFunction *ParentFunc = getBATParentFunction (*Func))
747+ Func = ParentFunc;
750748
751- return std::pair{ParentFunc , IsRet};
749+ return std::pair{Func , IsRet};
752750 };
753751
754752 auto [FromFunc, IsReturn] = handleAddress (From, /* IsFrom*/ true );
@@ -1318,6 +1316,14 @@ std::error_code DataAggregator::printLBRHeatMap() {
13181316 }
13191317 Heatmap HM (opts::HeatmapBlock, opts::HeatmapMinAddress,
13201318 opts::HeatmapMaxAddress, getTextSections (BC));
1319+ auto getSymbolValue = [&](const MCSymbol *Symbol) -> uint64_t {
1320+ if (Symbol)
1321+ if (ErrorOr<uint64_t > SymValue = BC->getSymbolValue (*Symbol))
1322+ return SymValue.get ();
1323+ return 0 ;
1324+ };
1325+ HM.HotStart = getSymbolValue (BC->getHotTextStartSymbol ());
1326+ HM.HotEnd = getSymbolValue (BC->getHotTextEndSymbol ());
13211327
13221328 if (!NumTotalSamples) {
13231329 if (opts::BasicAggregation) {
@@ -1351,15 +1357,14 @@ std::error_code DataAggregator::printLBRHeatMap() {
13511357 exit (1 );
13521358 }
13531359
1354- HM.print (opts::OutputFilename);
1355- if (opts::OutputFilename == " -" )
1356- HM.printCDF (opts::OutputFilename);
1357- else
1358- HM.printCDF (opts::OutputFilename + " .csv" );
1359- if (opts::OutputFilename == " -" )
1360- HM.printSectionHotness (opts::OutputFilename);
1361- else
1362- HM.printSectionHotness (opts::OutputFilename + " -section-hotness.csv" );
1360+ HM.print (opts::HeatmapOutput);
1361+ if (opts::HeatmapOutput == " -" ) {
1362+ HM.printCDF (opts::HeatmapOutput);
1363+ HM.printSectionHotness (opts::HeatmapOutput);
1364+ } else {
1365+ HM.printCDF (opts::HeatmapOutput + " .csv" );
1366+ HM.printSectionHotness (opts::HeatmapOutput + " -section-hotness.csv" );
1367+ }
13631368
13641369 return std::error_code ();
13651370}
@@ -1386,7 +1391,7 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
13861391 const uint64_t TraceTo = NextLBR->From ;
13871392 const BinaryFunction *TraceBF =
13881393 getBinaryFunctionContainingAddress (TraceFrom);
1389- if (opts::HeatmapMode) {
1394+ if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive ) {
13901395 FTInfo &Info = FallthroughLBRs[Trace (TraceFrom, TraceTo)];
13911396 ++Info.InternCount ;
13921397 } else if (TraceBF && TraceBF->containsAddress (TraceTo)) {
@@ -1424,7 +1429,7 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
14241429 NextLBR = &LBR;
14251430
14261431 // Record branches outside binary functions for heatmap.
1427- if (opts::HeatmapMode) {
1432+ if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive ) {
14281433 TakenBranchInfo &Info = BranchLBRs[Trace (LBR.From , LBR.To )];
14291434 ++Info.TakenCount ;
14301435 continue ;
@@ -1439,26 +1444,13 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
14391444 }
14401445 // Record LBR addresses not covered by fallthroughs (bottom-of-stack source
14411446 // and top-of-stack target) as basic samples for heatmap.
1442- if (opts::HeatmapMode && !Sample.LBR .empty ()) {
1447+ if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive &&
1448+ !Sample.LBR .empty ()) {
14431449 ++BasicSamples[Sample.LBR .front ().To ];
14441450 ++BasicSamples[Sample.LBR .back ().From ];
14451451 }
14461452}
14471453
1448- void DataAggregator::printColdSamplesDiagnostic () const {
1449- if (NumColdSamples > 0 ) {
1450- const float ColdSamples = NumColdSamples * 100 .0f / NumTotalSamples;
1451- outs () << " PERF2BOLT: " << NumColdSamples
1452- << format (" (%.1f%%)" , ColdSamples)
1453- << " samples recorded in cold regions of split functions.\n " ;
1454- if (ColdSamples > 5 .0f )
1455- outs ()
1456- << " WARNING: The BOLT-processed binary where samples were collected "
1457- " likely used bad data or your service observed a large shift in "
1458- " profile. You may want to audit this\n " ;
1459- }
1460- }
1461-
14621454void DataAggregator::printLongRangeTracesDiagnostic () const {
14631455 outs () << " PERF2BOLT: out of range traces involving unknown regions: "
14641456 << NumLongRangeTraces;
@@ -1499,7 +1491,6 @@ void DataAggregator::printBranchSamplesDiagnostics() const {
14991491 " collection. The generated data may be ineffective for improving "
15001492 " performance\n\n " ;
15011493 printLongRangeTracesDiagnostic ();
1502- printColdSamplesDiagnostic ();
15031494}
15041495
15051496void DataAggregator::printBasicSamplesDiagnostics (
@@ -1511,7 +1502,6 @@ void DataAggregator::printBasicSamplesDiagnostics(
15111502 " binary is probably not the same binary used during profiling "
15121503 " collection. The generated data may be ineffective for improving "
15131504 " performance\n\n " ;
1514- printColdSamplesDiagnostic ();
15151505}
15161506
15171507void DataAggregator::printBranchStacksDiagnostics (
0 commit comments