diff options
Diffstat (limited to 'llvm/tools/llvm-profdata/llvm-profdata.cpp')
| -rw-r--r-- | llvm/tools/llvm-profdata/llvm-profdata.cpp | 157 |
1 files changed, 79 insertions, 78 deletions
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 66d70120ac9b..fd67cac3cdd2 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -521,9 +521,9 @@ adjustInstrProfile(std::unique_ptr<WriterContext> &WC, // Find hot/warm functions in sample profile which is cold in instr profile // and adjust the profiles of those functions in the instr profile. for (const auto &PD : Reader->getProfiles()) { - StringRef FName = PD.getKey(); - const sampleprof::FunctionSamples &FS = PD.getValue(); - auto It = InstrProfileMap.find(FName); + auto &FContext = PD.first; + const sampleprof::FunctionSamples &FS = PD.second; + auto It = InstrProfileMap.find(FContext.toString()); if (FS.getHeadSamples() > ColdSampleThreshold && It != InstrProfileMap.end() && It->second.MaxCount <= ColdInstrThreshold && @@ -690,7 +690,7 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, bool SampleMergeColdContext, bool SampleTrimColdContext, bool SampleColdContextFrameDepth, FailureMode FailMode) { using namespace sampleprof; - StringMap<FunctionSamples> ProfileMap; + SampleProfileMap ProfileMap; SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers; LLVMContext Context; sampleprof::ProfileSymbolList WriterList; @@ -716,7 +716,7 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, continue; } - StringMap<FunctionSamples> &Profiles = Reader->getProfiles(); + SampleProfileMap &Profiles = Reader->getProfiles(); if (ProfileIsProbeBased.hasValue() && ProfileIsProbeBased != FunctionSamples::ProfileIsProbeBased) exitWithError( @@ -725,19 +725,19 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, if (ProfileIsCS.hasValue() && ProfileIsCS != FunctionSamples::ProfileIsCS) exitWithError("cannot merge CS profile with non-CS profile"); ProfileIsCS = FunctionSamples::ProfileIsCS; - for (StringMap<FunctionSamples>::iterator I = Profiles.begin(), - E = Profiles.end(); + for (SampleProfileMap::iterator I = Profiles.begin(), E = Profiles.end(); I != E; ++I) { sampleprof_error Result = sampleprof_error::success; FunctionSamples Remapped = Remapper ? remapSamples(I->second, *Remapper, Result) : FunctionSamples(); FunctionSamples &Samples = Remapper ? Remapped : I->second; - StringRef FName = Samples.getNameWithContext(); - MergeResult(Result, ProfileMap[FName].merge(Samples, Input.Weight)); + SampleContext FContext = Samples.getContext(); + MergeResult(Result, ProfileMap[FContext].merge(Samples, Input.Weight)); if (Result != sampleprof_error::success) { std::error_code EC = make_error_code(Result); - handleMergeWriterError(errorCodeToError(EC), Input.Filename, FName); + handleMergeWriterError(errorCodeToError(EC), Input.Filename, + FContext.toString()); } } @@ -759,7 +759,7 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, SampleContextTrimmer(ProfileMap) .trimAndMergeColdContextProfiles( SampleProfColdThreshold, SampleTrimColdContext, - SampleMergeColdContext, SampleColdContextFrameDepth); + SampleMergeColdContext, SampleColdContextFrameDepth, false); } auto WriterOrErr = @@ -836,7 +836,7 @@ static void parseInputFilenamesFile(MemoryBuffer *Buffer, if (SanitizedEntry.startswith("#")) continue; // If there's no comma, it's an unweighted profile. - else if (SanitizedEntry.find(',') == StringRef::npos) + else if (!SanitizedEntry.contains(',')) addWeightedInput(WFV, {std::string(SanitizedEntry), 1}); else addWeightedInput(WFV, parseWeightedFile(SanitizedEntry)); @@ -1022,8 +1022,8 @@ static void overlapInstrProfile(const std::string &BaseFilename, namespace { struct SampleOverlapStats { - StringRef BaseName; - StringRef TestName; + SampleContext BaseName; + SampleContext TestName; // Number of overlap units uint64_t OverlapCount; // Total samples of overlap units @@ -1226,6 +1226,9 @@ public: /// Load profiles specified by BaseFilename and TestFilename. std::error_code loadProfiles(); + using FuncSampleStatsMap = + std::unordered_map<SampleContext, FuncSampleStats, SampleContext::Hash>; + private: SampleOverlapStats ProfOverlap; SampleOverlapStats HotFuncOverlap; @@ -1236,8 +1239,8 @@ private: std::unique_ptr<sampleprof::SampleProfileReader> TestReader; // BaseStats and TestStats hold FuncSampleStats for each function, with // function name as the key. - StringMap<FuncSampleStats> BaseStats; - StringMap<FuncSampleStats> TestStats; + FuncSampleStatsMap BaseStats; + FuncSampleStatsMap TestStats; // Low similarity threshold in floating point number double LowSimilarityThreshold; // Block samples above BaseHotThreshold or TestHotThreshold are considered hot @@ -1276,8 +1279,8 @@ private: void updateHotBlockOverlap(uint64_t BaseSample, uint64_t TestSample, uint64_t HotBlockCount); - void getHotFunctions(const StringMap<FuncSampleStats> &ProfStats, - StringMap<FuncSampleStats> &HotFunc, + void getHotFunctions(const FuncSampleStatsMap &ProfStats, + FuncSampleStatsMap &HotFunc, uint64_t HotThreshold) const; void computeHotFuncOverlap(); @@ -1381,26 +1384,26 @@ void SampleOverlapAggregator::updateHotBlockOverlap(uint64_t BaseSample, } void SampleOverlapAggregator::getHotFunctions( - const StringMap<FuncSampleStats> &ProfStats, - StringMap<FuncSampleStats> &HotFunc, uint64_t HotThreshold) const { + const FuncSampleStatsMap &ProfStats, FuncSampleStatsMap &HotFunc, + uint64_t HotThreshold) const { for (const auto &F : ProfStats) { if (isFunctionHot(F.second, HotThreshold)) - HotFunc.try_emplace(F.first(), F.second); + HotFunc.emplace(F.first, F.second); } } void SampleOverlapAggregator::computeHotFuncOverlap() { - StringMap<FuncSampleStats> BaseHotFunc; + FuncSampleStatsMap BaseHotFunc; getHotFunctions(BaseStats, BaseHotFunc, BaseHotThreshold); HotFuncOverlap.BaseCount = BaseHotFunc.size(); - StringMap<FuncSampleStats> TestHotFunc; + FuncSampleStatsMap TestHotFunc; getHotFunctions(TestStats, TestHotFunc, TestHotThreshold); HotFuncOverlap.TestCount = TestHotFunc.size(); HotFuncOverlap.UnionCount = HotFuncOverlap.TestCount; for (const auto &F : BaseHotFunc) { - if (TestHotFunc.count(F.first())) + if (TestHotFunc.count(F.first)) ++HotFuncOverlap.OverlapCount; else ++HotFuncOverlap.UnionCount; @@ -1612,23 +1615,25 @@ double SampleOverlapAggregator::computeSampleFunctionOverlap( void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { using namespace sampleprof; - StringMap<const FunctionSamples *> BaseFuncProf; + std::unordered_map<SampleContext, const FunctionSamples *, + SampleContext::Hash> + BaseFuncProf; const auto &BaseProfiles = BaseReader->getProfiles(); for (const auto &BaseFunc : BaseProfiles) { - BaseFuncProf.try_emplace(BaseFunc.second.getNameWithContext(), - &(BaseFunc.second)); + BaseFuncProf.emplace(BaseFunc.second.getContext(), &(BaseFunc.second)); } ProfOverlap.UnionCount = BaseFuncProf.size(); const auto &TestProfiles = TestReader->getProfiles(); for (const auto &TestFunc : TestProfiles) { SampleOverlapStats FuncOverlap; - FuncOverlap.TestName = TestFunc.second.getNameWithContext(); + FuncOverlap.TestName = TestFunc.second.getContext(); assert(TestStats.count(FuncOverlap.TestName) && "TestStats should have records for all functions in test profile " "except inlinees"); FuncOverlap.TestSample = TestStats[FuncOverlap.TestName].SampleSum; + bool Matched = false; const auto Match = BaseFuncProf.find(FuncOverlap.TestName); if (Match == BaseFuncProf.end()) { const FuncSampleStats &FuncStats = TestStats[FuncOverlap.TestName]; @@ -1650,7 +1655,7 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { // Two functions match with each other. Compute function-level overlap and // aggregate them into profile-level overlap. - FuncOverlap.BaseName = Match->second->getNameWithContext(); + FuncOverlap.BaseName = Match->second->getContext(); assert(BaseStats.count(FuncOverlap.BaseName) && "BaseStats should have records for all functions in base profile " "except inlinees"); @@ -1673,6 +1678,7 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { // Remove matched base functions for later reporting functions not found // in test profile. BaseFuncProf.erase(Match); + Matched = true; } // Print function-level similarity information if specified by options. @@ -1680,11 +1686,10 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { "TestStats should have records for all functions in test profile " "except inlinees"); if (TestStats[FuncOverlap.TestName].MaxSample >= FuncFilter.ValueCutoff || - (Match != BaseFuncProf.end() && - FuncOverlap.Similarity < LowSimilarityThreshold) || - (Match != BaseFuncProf.end() && !FuncFilter.NameFilter.empty() && - FuncOverlap.BaseName.find(FuncFilter.NameFilter) != - FuncOverlap.BaseName.npos)) { + (Matched && FuncOverlap.Similarity < LowSimilarityThreshold) || + (Matched && !FuncFilter.NameFilter.empty() && + FuncOverlap.BaseName.toString().find(FuncFilter.NameFilter) != + std::string::npos)) { assert(ProfOverlap.BaseSample > 0 && "Total samples in base profile should be greater than 0"); FuncOverlap.BaseWeight = @@ -1699,11 +1704,10 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { // Traverse through functions in base profile but not in test profile. for (const auto &F : BaseFuncProf) { - assert(BaseStats.count(F.second->getNameWithContext()) && + assert(BaseStats.count(F.second->getContext()) && "BaseStats should have records for all functions in base profile " "except inlinees"); - const FuncSampleStats &FuncStats = - BaseStats[F.second->getNameWithContext()]; + const FuncSampleStats &FuncStats = BaseStats[F.second->getContext()]; ++ProfOverlap.BaseUniqueCount; ProfOverlap.BaseUniqueSample += FuncStats.SampleSum; @@ -1734,7 +1738,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() { FuncSampleStats FuncStats; getFuncSampleStats(I.second, FuncStats, BaseHotThreshold); ProfOverlap.BaseSample += FuncStats.SampleSum; - BaseStats.try_emplace(I.second.getNameWithContext(), FuncStats); + BaseStats.emplace(I.second.getContext(), FuncStats); } const auto &TestProf = TestReader->getProfiles(); @@ -1743,7 +1747,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() { FuncSampleStats FuncStats; getFuncSampleStats(I.second, FuncStats, TestHotThreshold); ProfOverlap.TestSample += FuncStats.SampleSum; - TestStats.try_emplace(I.second.getNameWithContext(), FuncStats); + TestStats.emplace(I.second.getContext(), FuncStats); } ProfOverlap.BaseName = StringRef(BaseFilename); @@ -1807,13 +1811,15 @@ void SampleOverlapAggregator::dumpFuncSimilarity(raw_fd_ostream &OS) const { FOS.PadToColumn(TestSampleCol); FOS << F.second.TestSample; FOS.PadToColumn(FuncNameCol); - FOS << F.second.TestName << "\n"; + FOS << F.second.TestName.toString() << "\n"; } } void SampleOverlapAggregator::dumpProgramSummary(raw_fd_ostream &OS) const { - OS << "Profile overlap infomation for base_profile: " << ProfOverlap.BaseName - << " and test_profile: " << ProfOverlap.TestName << "\nProgram level:\n"; + OS << "Profile overlap infomation for base_profile: " + << ProfOverlap.BaseName.toString() + << " and test_profile: " << ProfOverlap.TestName.toString() + << "\nProgram level:\n"; OS << " Whole program profile similarity: " << format("%.3f%%", ProfOverlap.Similarity * 100) << "\n"; @@ -1909,22 +1915,13 @@ std::error_code SampleOverlapAggregator::loadProfiles() { // Load BaseHotThreshold and TestHotThreshold as 99-percentile threshold in // profile summary. - const uint64_t HotCutoff = 990000; ProfileSummary &BasePS = BaseReader->getSummary(); - for (const auto &SummaryEntry : BasePS.getDetailedSummary()) { - if (SummaryEntry.Cutoff == HotCutoff) { - BaseHotThreshold = SummaryEntry.MinCount; - break; - } - } - ProfileSummary &TestPS = TestReader->getSummary(); - for (const auto &SummaryEntry : TestPS.getDetailedSummary()) { - if (SummaryEntry.Cutoff == HotCutoff) { - TestHotThreshold = SummaryEntry.MinCount; - break; - } - } + BaseHotThreshold = + ProfileSummaryBuilder::getHotCountThreshold(BasePS.getDetailedSummary()); + TestHotThreshold = + ProfileSummaryBuilder::getHotCountThreshold(TestPS.getDetailedSummary()); + return std::error_code(); } @@ -2111,9 +2108,8 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, if (FuncIsCS != ShowCS) continue; } - bool Show = - ShowAllFunctions || (!ShowFunction.empty() && - Func.Name.find(ShowFunction) != Func.Name.npos); + bool Show = ShowAllFunctions || + (!ShowFunction.empty() && Func.Name.contains(ShowFunction)); bool doTextFormatDump = (Show && TextFormat); @@ -2271,7 +2267,7 @@ static void showSectionInfo(sampleprof::SampleProfileReader *Reader, namespace { struct HotFuncInfo { - StringRef FuncName; + std::string FuncName; uint64_t TotalCount; double TotalCountPercent; uint64_t MaxCount; @@ -2282,8 +2278,8 @@ struct HotFuncInfo { EntryCount(0) {} HotFuncInfo(StringRef FN, uint64_t TS, double TSP, uint64_t MS, uint64_t ES) - : FuncName(FN), TotalCount(TS), TotalCountPercent(TSP), MaxCount(MS), - EntryCount(ES) {} + : FuncName(FN.begin(), FN.end()), TotalCount(TS), TotalCountPercent(TSP), + MaxCount(MS), EntryCount(ES) {} }; } // namespace @@ -2298,7 +2294,7 @@ static void dumpHotFunctionList(const std::vector<std::string> &ColumnTitle, uint64_t HotFuncCount, uint64_t TotalFuncCount, uint64_t HotProfCount, uint64_t TotalProfCount, const std::string &HotFuncMetric, - raw_fd_ostream &OS) { + uint32_t TopNFunctions, raw_fd_ostream &OS) { assert(ColumnOffset.size() == ColumnTitle.size() && "ColumnOffset and ColumnTitle should have the same size"); assert(ColumnTitle.size() >= 4 && @@ -2327,7 +2323,10 @@ static void dumpHotFunctionList(const std::vector<std::string> &ColumnTitle, } FOS << "\n"; - for (const HotFuncInfo &R : PrintValues) { + uint32_t Count = 0; + for (const auto &R : PrintValues) { + if (TopNFunctions && (Count++ == TopNFunctions)) + break; FOS.PadToColumn(ColumnOffset[0]); FOS << R.TotalCount << " (" << format("%.2f%%", R.TotalCountPercent) << ")"; FOS.PadToColumn(ColumnOffset[1]); @@ -2339,9 +2338,9 @@ static void dumpHotFunctionList(const std::vector<std::string> &ColumnTitle, } } -static int -showHotFunctionList(const StringMap<sampleprof::FunctionSamples> &Profiles, - ProfileSummary &PS, raw_fd_ostream &OS) { +static int showHotFunctionList(const sampleprof::SampleProfileMap &Profiles, + ProfileSummary &PS, uint32_t TopN, + raw_fd_ostream &OS) { using namespace sampleprof; const uint32_t HotFuncCutoff = 990000; @@ -2391,18 +2390,19 @@ showHotFunctionList(const StringMap<sampleprof::FunctionSamples> &Profiles, ? (Func.getTotalSamples() * 100.0) / ProfileTotalSample : 0; PrintValues.emplace_back(HotFuncInfo( - Func.getNameWithContext(), Func.getTotalSamples(), TotalSamplePercent, - FuncPair.second.second, Func.getEntrySamples())); + Func.getContext().toString(), Func.getTotalSamples(), + TotalSamplePercent, FuncPair.second.second, Func.getEntrySamples())); } dumpHotFunctionList(ColumnTitle, ColumnOffset, PrintValues, HotFuncCount, Profiles.size(), HotFuncSample, ProfileTotalSample, - Metric, OS); + Metric, TopN, OS); return 0; } static int showSampleProfile(const std::string &Filename, bool ShowCounts, - bool ShowAllFunctions, bool ShowDetailedSummary, + uint32_t TopN, bool ShowAllFunctions, + bool ShowDetailedSummary, const std::string &ShowFunction, bool ShowProfileSymbolList, bool ShowSectionInfoOnly, bool ShowHotFuncList, @@ -2426,7 +2426,8 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts, if (ShowAllFunctions || ShowFunction.empty()) Reader->dump(OS); else - Reader->dumpFunctionProfile(ShowFunction, OS); + // TODO: parse context string to support filtering by contexts. + Reader->dumpFunctionProfile(StringRef(ShowFunction), OS); if (ShowProfileSymbolList) { std::unique_ptr<sampleprof::ProfileSymbolList> ReaderList = @@ -2440,8 +2441,8 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts, PS.printDetailedSummary(OS); } - if (ShowHotFuncList) - showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), OS); + if (ShowHotFuncList || TopN) + showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), TopN, OS); return 0; } @@ -2532,10 +2533,10 @@ static int show_main(int argc, const char *argv[]) { ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction, TextFormat, ShowBinaryIds, OS); else - return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, - ShowDetailedSummary, ShowFunction, - ShowProfileSymbolList, ShowSectionInfoOnly, - ShowHotFuncList, OS); + return showSampleProfile(Filename, ShowCounts, TopNFunctions, + ShowAllFunctions, ShowDetailedSummary, + ShowFunction, ShowProfileSymbolList, + ShowSectionInfoOnly, ShowHotFuncList, OS); } int main(int argc, const char *argv[]) { |
