@@ -68,6 +68,12 @@ FilterPID("pid",
6868 cl::Optional,
6969 cl::cat(AggregatorCategory));
7070
71+ static cl::list<uint64_t >
72+ HeatmapZoomOut (" heatmap-zoom-out" , cl::CommaSeparated,
73+ cl::desc (" print secondary heatmaps with given bucket sizes" ),
74+ cl::value_desc(" bucket_size" ), cl::Optional,
75+ cl::cat(HeatmapCategory));
76+
7177static cl::opt<bool >
7278IgnoreBuildID (" ignore-build-id" ,
7379 cl::desc (" continue even if build-ids in input binary and perf.data mismatch" ),
@@ -1210,71 +1216,80 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
12101216 ErrorOr<StringRef> TypeOrErr = parseString (FieldSeparator);
12111217 if (std::error_code EC = TypeOrErr.getError ())
12121218 return EC;
1213- enum AggregatedLBREntry { TRACE, BRANCH, FT, FT_EXTERNAL_ORIGIN, INVALID };
1219+ enum AggregatedLBREntry {
1220+ TRACE,
1221+ SAMPLE,
1222+ BRANCH,
1223+ FT,
1224+ FT_EXTERNAL_ORIGIN,
1225+ INVALID
1226+ };
12141227 auto Type = StringSwitch<AggregatedLBREntry>(TypeOrErr.get ())
12151228 .Case (" T" , TRACE)
1229+ .Case (" S" , SAMPLE)
12161230 .Case (" B" , BRANCH)
12171231 .Case (" F" , FT)
12181232 .Case (" f" , FT_EXTERNAL_ORIGIN)
12191233 .Default (INVALID);
12201234 if (Type == INVALID) {
1221- reportError (" expected T, B, F or f" );
1235+ reportError (" expected T, S, B, F or f" );
12221236 return make_error_code (llvm::errc::io_error);
12231237 }
12241238
1225- while (checkAndConsumeFS ()) {
1226- }
1227- ErrorOr<Location> From = parseLocationOrOffset ();
1228- if (std::error_code EC = From.getError ())
1229- return EC;
1239+ std::optional<Location> Addrs[3 ];
1240+ int AddrNum = 2 ;
1241+ if (Type == TRACE)
1242+ AddrNum = 3 ;
1243+ else if (Type == SAMPLE)
1244+ AddrNum = 1 ;
12301245
1231- while (checkAndConsumeFS ()) {
1232- }
1233- ErrorOr<Location> To = parseLocationOrOffset ();
1234- if (std::error_code EC = To.getError ())
1235- return EC;
1246+ int64_t Counters[2 ];
1247+ int CounterNum = 1 ;
1248+ if (Type == BRANCH)
1249+ CounterNum = 2 ;
12361250
1237- ErrorOr<Location> TraceFtEnd = std::error_code ();
1238- if (Type == AggregatedLBREntry::TRACE) {
1251+ for (int I = 0 ; I < AddrNum; ++I) {
12391252 while (checkAndConsumeFS ()) {
12401253 }
1241- TraceFtEnd = parseLocationOrOffset ();
1242- if (std::error_code EC = TraceFtEnd.getError ())
1243- return EC;
1244- }
1245-
1246- while (checkAndConsumeFS ()) {
1254+ if (ErrorOr<Location> Addr = parseLocationOrOffset ())
1255+ Addrs[I] = Addr.get ();
1256+ else
1257+ return Addr.getError ();
12471258 }
1248- ErrorOr<int64_t > Frequency =
1249- parseNumberField (FieldSeparator, Type != AggregatedLBREntry::BRANCH);
1250- if (std::error_code EC = Frequency.getError ())
1251- return EC;
12521259
1253- uint64_t Mispreds = 0 ;
1254- if (Type == AggregatedLBREntry::BRANCH) {
1260+ for (int I = 0 ; I < CounterNum; ++I) {
12551261 while (checkAndConsumeFS ()) {
12561262 }
1257- ErrorOr<int64_t > MispredsOrErr = parseNumberField (FieldSeparator, true );
1258- if (std::error_code EC = MispredsOrErr. getError ())
1259- return EC;
1260- Mispreds = static_cast < uint64_t >(MispredsOrErr. get () );
1263+ if ( ErrorOr<int64_t > Count = parseNumberField (FieldSeparator, I + 1 == CounterNum))
1264+ Counters[I] = Count. get ();
1265+ else
1266+ return Count. getError ( );
12611267 }
12621268
12631269 if (!checkAndConsumeNewLine ()) {
12641270 reportError (" expected end of line" );
12651271 return make_error_code (llvm::errc::io_error);
12661272 }
12671273
1268- BinaryFunction *FromFunc = getBinaryFunctionContainingAddress (From->Offset );
1269- BinaryFunction *ToFunc = getBinaryFunctionContainingAddress (To->Offset );
1274+ const uint64_t FromOffset = Addrs[0 ]->Offset ;
1275+ BinaryFunction *FromFunc = getBinaryFunctionContainingAddress (FromOffset);
1276+ if (FromFunc)
1277+ FromFunc->setHasProfileAvailable ();
12701278
1271- for (BinaryFunction *BF : {FromFunc, ToFunc})
1272- if (BF)
1273- BF->setHasProfileAvailable ();
1279+ if (Type == SAMPLE) {
1280+ BasicSamples[FromOffset] += Counters[0 ];
1281+ return std::error_code ();
1282+ }
1283+
1284+ const uint64_t ToOffset = Addrs[1 ]->Offset ;
1285+ BinaryFunction *ToFunc = getBinaryFunctionContainingAddress (ToOffset);
1286+ if (ToFunc)
1287+ ToFunc->setHasProfileAvailable ();
12741288
1275- uint64_t Count = static_cast <uint64_t >(Frequency.get ());
1289+ int64_t Count = Counters[0 ];
1290+ int64_t Mispreds = Counters[1 ];
12761291
1277- Trace Trace (From-> Offset , To-> Offset );
1292+ Trace Trace (FromOffset, ToOffset );
12781293 // Taken trace
12791294 if (Type == TRACE || Type == BRANCH) {
12801295 TakenBranchInfo &Info = BranchLBRs[Trace];
@@ -1285,8 +1300,9 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
12851300 }
12861301 // Construct fallthrough part of the trace
12871302 if (Type == TRACE) {
1288- Trace.From = To->Offset ;
1289- Trace.To = TraceFtEnd->Offset ;
1303+ const uint64_t TraceFtEndOffset = Addrs[2 ]->Offset ;
1304+ Trace.From = ToOffset;
1305+ Trace.To = TraceFtEndOffset;
12901306 Type = FromFunc == ToFunc ? FT : FT_EXTERNAL_ORIGIN;
12911307 }
12921308 // Add fallthrough trace
@@ -1365,6 +1381,15 @@ std::error_code DataAggregator::printLBRHeatMap() {
13651381 HM.printCDF (opts::HeatmapOutput + " .csv" );
13661382 HM.printSectionHotness (opts::HeatmapOutput + " -section-hotness.csv" );
13671383 }
1384+ // Provide coarse-grained heatmap if requested via --heatmap-zoom-out
1385+ for (const uint64_t NewBucketSize : opts::HeatmapZoomOut) {
1386+ if (!HM.resizeBucket (NewBucketSize))
1387+ break ;
1388+ if (opts::HeatmapOutput == " -" )
1389+ HM.print (opts::HeatmapOutput);
1390+ else
1391+ HM.print (formatv (" {0}-{1}" , opts::HeatmapOutput, NewBucketSize).str ());
1392+ }
13681393
13691394 return std::error_code ();
13701395}
0 commit comments