summaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-profdata/llvm-profdata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-profdata/llvm-profdata.cpp')
-rw-r--r--llvm/tools/llvm-profdata/llvm-profdata.cpp157
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[]) {