diff options
Diffstat (limited to 'llvm/tools/llvm-profgen/ProfileGenerator.cpp')
-rw-r--r-- | llvm/tools/llvm-profgen/ProfileGenerator.cpp | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp index c4028e6..5aa4410 100644 --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -196,6 +196,48 @@ void ProfileGeneratorBase::showDensitySuggestion(double Density) { << "% total samples: " << format("%.1f", Density) << "\n"; } +bool ProfileGeneratorBase::filterAmbiguousProfile(FunctionSamples &FS) { + for (const auto &Prefix : FuncPrefixsToFilter) { + if (FS.getFuncName().starts_with(Prefix)) + return true; + } + + // Filter the function profiles for the inlinees. It's useful for fuzzy + // profile matching which flattens the profile and inlinees' samples are + // merged into top-level function. + for (auto &Callees : + const_cast<CallsiteSampleMap &>(FS.getCallsiteSamples())) { + auto &CalleesMap = Callees.second; + for (auto I = CalleesMap.begin(); I != CalleesMap.end();) { + auto FS = I++; + if (filterAmbiguousProfile(FS->second)) + CalleesMap.erase(FS); + } + } + return false; +} + +// For built-in local initialization function such as __cxx_global_var_init, +// __tls_init prefix function, there could be multiple versions of the functions +// in the final binary. However, in the profile generation, we call +// getCanonicalFnName to canonicalize the names which strips the suffixes. +// Therefore, samples from different functions queries the same profile and the +// samples are merged. As the functions are essentially different, entries of +// the merged profile are ambiguous. In sample loader, the IR from one version +// would be attributed towards a merged entries, which is inaccurate. Especially +// for fuzzy profile matching, it gets multiple callsites(from different +// function) but used to match one callsite, which misleads the matching and +// causes a lot of false positives report. Hence, we want to filter them out +// from the profile map during the profile generation time. The profiles are all +// cold functions, it won't have perf impact. +void ProfileGeneratorBase::filterAmbiguousProfile(SampleProfileMap &Profiles) { + for (auto I = ProfileMap.begin(); I != ProfileMap.end();) { + auto FS = I++; + if (filterAmbiguousProfile(FS->second)) + ProfileMap.erase(FS); + } +} + double ProfileGeneratorBase::calculateDensity(const SampleProfileMap &Profiles, uint64_t HotCntThreshold) { double Density = DBL_MAX; @@ -491,6 +533,7 @@ void ProfileGenerator::generateProfile() { void ProfileGenerator::postProcessProfiles() { computeSummaryAndThreshold(ProfileMap); trimColdProfiles(ProfileMap, ColdCountThreshold); + filterAmbiguousProfile(ProfileMap); calculateAndShowDensity(ProfileMap); } @@ -1024,6 +1067,7 @@ void CSProfileGenerator::postProcessProfiles() { CSConverter.convertCSProfiles(); FunctionSamples::ProfileIsCS = false; } + filterAmbiguousProfile(ProfileMap); } void ProfileGeneratorBase::computeSummaryAndThreshold( |