diff options
Diffstat (limited to 'llvm/lib/ProfileData/SampleProf.cpp')
-rw-r--r-- | llvm/lib/ProfileData/SampleProf.cpp | 32 |
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); } } |