diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -1000,6 +1000,10 @@ /// Print all sections. void printSections(raw_ostream &OS) const; + /// Return a map from section names to the address range. + StringMap> + getSectionNameToAddressRangeMap() const; + /// Return largest section containing the given \p Address. These /// functions only work for allocatable sections, i.e. ones with non-zero /// addresses. diff --git a/bolt/include/bolt/Profile/Heatmap.h b/bolt/include/bolt/Profile/Heatmap.h --- a/bolt/include/bolt/Profile/Heatmap.h +++ b/bolt/include/bolt/Profile/Heatmap.h @@ -9,6 +9,7 @@ #ifndef BOLT_PROFILE_HEATMAP_H #define BOLT_PROFILE_HEATMAP_H +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include #include @@ -34,11 +35,16 @@ /// Map buckets to the number of samples. std::map Map; + /// Map section names to their address range. + const StringMap> SectionNameToAddressRange; + public: - explicit Heatmap(uint64_t BucketSize = 4096, uint64_t MinAddress = 0, - uint64_t MaxAddress = std::numeric_limits::max()) - : BucketSize(BucketSize), MinAddress(MinAddress), - MaxAddress(MaxAddress){}; + explicit Heatmap( + uint64_t BucketSize = 4096, uint64_t MinAddress = 0, + uint64_t MaxAddress = std::numeric_limits::max(), + StringMap> SectionNameToAddressRange = {}) + : BucketSize(BucketSize), MinAddress(MinAddress), MaxAddress(MaxAddress), + SectionNameToAddressRange(SectionNameToAddressRange){}; inline bool ignoreAddress(uint64_t Address) const { return (Address > MaxAddress) || (Address < MinAddress); @@ -65,6 +71,10 @@ void printCDF(raw_ostream &OS) const; + void printSectionHotness(StringRef Filename) const; + + void printSectionHotness(raw_ostream &OS) const; + size_t size() const { return Map.size(); } }; 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 @@ -1768,6 +1768,16 @@ return *Section; } +StringMap> +BinaryContext::getSectionNameToAddressRangeMap() const { + StringMap> M; + for (const auto &elem : AddressToSection) { + M[elem.second->getName()] = + std::make_pair(elem.second->getAddress(), elem.second->getEndAddress()); + } + return M; +} + BinarySection &BinaryContext::registerSection(SectionRef Section) { return registerSection(new BinarySection(*this, Section)); } 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 @@ -1292,7 +1292,7 @@ opts::HeatmapMinAddress = KernelBaseAddr; } Heatmap HM(opts::HeatmapBlock, opts::HeatmapMinAddress, - opts::HeatmapMaxAddress); + opts::HeatmapMaxAddress, BC->getSectionNameToAddressRangeMap()); uint64_t NumTotalSamples = 0; if (opts::BasicAggregation) { @@ -1374,6 +1374,10 @@ HM.printCDF(opts::OutputFilename); else HM.printCDF(opts::OutputFilename + ".csv"); + if (opts::OutputFilename == "-") + HM.printSectionHotness(opts::OutputFilename); + else + HM.printSectionHotness(opts::OutputFilename + "-section-hotness.csv"); return std::error_code(); } diff --git a/bolt/lib/Profile/Heatmap.cpp b/bolt/lib/Profile/Heatmap.cpp --- a/bolt/lib/Profile/Heatmap.cpp +++ b/bolt/lib/Profile/Heatmap.cpp @@ -251,5 +251,51 @@ Counts.clear(); } +void Heatmap::printSectionHotness(StringRef FileName) const { + std::error_code EC; + raw_fd_ostream OS(FileName, EC, sys::fs::OpenFlags::OF_None); + if (EC) { + errs() << "error opening output file: " << EC.message() << '\n'; + exit(1); + } + printSectionHotness(OS); +} + +void Heatmap::printSectionHotness(raw_ostream &OS) const { + uint64_t NumTotalCounts = 0; + StringMap SectionHotness; + + for (const std::pair &KV : Map) { + auto Address = KV.first * BucketSize; + for (auto &Elem : SectionNameToAddressRange) { + if (Address >= Elem.getValue().first && + Address < Elem.getValue().second) { + SectionHotness[Elem.first()] += KV.second; + break; + } + } + NumTotalCounts += KV.second; + } + std::vector SectionNames; + for (auto &Elem : SectionNameToAddressRange) + SectionNames.push_back(Elem.first()); + + // Order section names by their starting address. + std::sort(SectionNames.begin(), SectionNames.end(), + [&](const StringRef &a, const StringRef &b) { + return SectionNameToAddressRange.lookup(a).first < + SectionNameToAddressRange.lookup(b).first; + }); + + assert(NumTotalCounts > 0 && + "total number of heatmap buckets should be greater than 0"); + + OS << "Section Name, Normalized Hotness"; + for (StringRef SectionName : SectionNames) { + OS << SectionName << ", " + << format("%.4f", 100.0 * SectionHotness[SectionName] / NumTotalCounts) + << "\n"; + } +} } // namespace bolt } // namespace llvm