diff --git a/bolt/docs/Heatmaps.md b/bolt/docs/Heatmaps.md --- a/bolt/docs/Heatmaps.md +++ b/bolt/docs/Heatmaps.md @@ -20,8 +20,10 @@ $ perf record -e cycles:u -j any,u [-p PID|-a] -- sleep ``` -Note that at the moment running with LBR (`-j any,u` or `-b`) is -a requirement. +Running with LBR (`-j any,u` or `-b`) is recommended. Heatmaps can be generated +from basic events by using the llvm-bolt-heatmap option `-nl` (no LBR) but +such heatmaps do not have the coverage provided by LBR and may only be useful +for finding event hotspots at larger code block granularities. Once the run is complete, and `perf.data` is generated, run llvm-bolt-heatmap: diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -1296,37 +1296,55 @@ uint64_t NumTotalSamples = 0; while (hasData()) { - ErrorOr SampleRes = parseBranchSample(); - if (std::error_code EC = SampleRes.getError()) { - if (EC == errc::no_such_process) - continue; - return EC; - } - - PerfBranchSample &Sample = SampleRes.get(); + if (opts::BasicAggregation) { + ErrorOr SampleRes = parseBasicSample(); + if (std::error_code EC = SampleRes.getError()) { + if (EC == errc::no_such_process) + continue; + return EC; + } + PerfBasicSample &Sample = SampleRes.get(); + HM.registerAddress(Sample.PC); + NumTotalSamples++; + } else { + ErrorOr SampleRes = parseBranchSample(); + if (std::error_code EC = SampleRes.getError()) { + if (EC == errc::no_such_process) + continue; + return EC; + } - // LBRs are stored in reverse execution order. NextLBR refers to the next - // executed branch record. - const LBREntry *NextLBR = nullptr; - for (const LBREntry &LBR : Sample.LBR) { - if (NextLBR) { - // Record fall-through trace. - const uint64_t TraceFrom = LBR.To; - const uint64_t TraceTo = NextLBR->From; - ++FallthroughLBRs[Trace(TraceFrom, TraceTo)].InternCount; + PerfBranchSample &Sample = SampleRes.get(); + + // LBRs are stored in reverse execution order. NextLBR refers to the next + // executed branch record. + const LBREntry *NextLBR = nullptr; + for (const LBREntry &LBR : Sample.LBR) { + if (NextLBR) { + // Record fall-through trace. + const uint64_t TraceFrom = LBR.To; + const uint64_t TraceTo = NextLBR->From; + ++FallthroughLBRs[Trace(TraceFrom, TraceTo)].InternCount; + } + NextLBR = &LBR; } - NextLBR = &LBR; - } - if (!Sample.LBR.empty()) { - HM.registerAddress(Sample.LBR.front().To); - HM.registerAddress(Sample.LBR.back().From); + if (!Sample.LBR.empty()) { + HM.registerAddress(Sample.LBR.front().To); + HM.registerAddress(Sample.LBR.back().From); + } + NumTotalSamples += Sample.LBR.size(); } - NumTotalSamples += Sample.LBR.size(); } if (!NumTotalSamples) { - errs() << "HEATMAP-ERROR: no LBR traces detected in profile. " - "Cannot build heatmap.\n"; + if (!opts::BasicAggregation) { + errs() << "HEATMAP-ERROR: no LBR traces detected in profile. " + "Cannot build heatmap. Use -nl for building heatmap from " + "basic events.\n"; + } else { + errs() << "HEATMAP-ERROR: no samples detected in profile. " + "Cannot build heatmap."; + } exit(1); }