aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/SampleProf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ProfileData/SampleProf.cpp')
-rw-r--r--llvm/lib/ProfileData/SampleProf.cpp32
1 files changed, 20 insertions, 12 deletions
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index b2b786a..60e707b 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -370,10 +370,8 @@ void SampleContextTrimmer::trimAndMergeColdContextProfiles(
}
void SampleContextTrimmer::canonicalizeContextProfiles() {
- StringSet<> ProfilesToBeRemoved;
- // Note that StringMap order is guaranteed to be top-down order,
- // this makes sure we make room for promoted/merged context in the
- // map, before we move profiles in the map.
+ std::vector<StringRef> ProfilesToBeRemoved;
+ StringMap<FunctionSamples> ProfilesToBeAdded;
for (auto &I : ProfileMap) {
FunctionSamples &FProfile = I.second;
StringRef ContextStr = FProfile.getNameWithContext();
@@ -383,17 +381,27 @@ void SampleContextTrimmer::canonicalizeContextProfiles() {
// Use the context string from FunctionSamples to update the keys of
// ProfileMap. They can get out of sync after context profile promotion
// through pre-inliner.
- auto Ret = ProfileMap.try_emplace(ContextStr, FProfile);
- assert(Ret.second && "Conext conflict during canonicalization");
- FProfile = Ret.first->second;
-
- // Track the context profile to remove
- ProfilesToBeRemoved.erase(ContextStr);
- ProfilesToBeRemoved.insert(I.first());
+ // Duplicate the function profile for later insertion to avoid a conflict
+ // caused by a context both to be add and to be removed. This could happen
+ // when a context is promoted to another context which is also promoted to
+ // the third context. For example, given an original context A @ B @ C that
+ // is promoted to B @ C and the original context B @ C which is promoted to
+ // just C, adding B @ C to the profile map while removing same context (but
+ // with different profiles) from the map can cause a conflict if they are
+ // not handled in a right order. This can be solved by just caching the
+ // profiles to be added.
+ auto Ret = ProfilesToBeAdded.try_emplace(ContextStr, FProfile);
+ (void)Ret;
+ assert(Ret.second && "Context conflict during canonicalization");
+ ProfilesToBeRemoved.push_back(I.first());
}
for (auto &I : ProfilesToBeRemoved) {
- ProfileMap.erase(I.first());
+ ProfileMap.erase(I);
+ }
+
+ for (auto &I : ProfilesToBeAdded) {
+ ProfileMap.try_emplace(I.first(), I.second);
}
}