diff options
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/llvm-profgen/ProfileGenerator.cpp | 44 | ||||
-rw-r--r-- | llvm/tools/llvm-profgen/ProfileGenerator.h | 8 |
2 files changed, 52 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( diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.h b/llvm/tools/llvm-profgen/ProfileGenerator.h index 88cf2dc..d258fb7 100644 --- a/llvm/tools/llvm-profgen/ProfileGenerator.h +++ b/llvm/tools/llvm-profgen/ProfileGenerator.h @@ -108,6 +108,10 @@ protected: void updateCallsiteSamples(); + void filterAmbiguousProfile(SampleProfileMap &Profiles); + + bool filterAmbiguousProfile(FunctionSamples &FS); + StringRef getCalleeNameForAddress(uint64_t TargetAddress); void computeSummaryAndThreshold(SampleProfileMap &ProfileMap); @@ -128,6 +132,10 @@ protected: virtual bool collectFunctionsFromLLVMProfile( std::unordered_set<const BinaryFunction *> &ProfiledFunctions) = 0; + // List of function prefix to filter out. + static constexpr const char *FuncPrefixsToFilter[] = {"__cxx_global_var_init", + "__tls_init"}; + // Thresholds from profile summary to answer isHotCount/isColdCount queries. uint64_t HotCountThreshold; |