diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -407,22 +407,6 @@ return getSamplesFor(CanonName); } - /// Return the samples collected for function \p F, create empty - /// FunctionSamples if it doesn't exist. - FunctionSamples *getOrCreateSamplesFor(const Function &F) { - std::string FGUID; - StringRef CanonName = FunctionSamples::getCanonicalFnName(F); - CanonName = getRepInFormat(CanonName, useMD5(), FGUID); - auto It = Profiles.find(CanonName); - if (It != Profiles.end()) - return &It->second; - if (!FGUID.empty()) { - assert(useMD5() && "New name should only be generated for md5 profile"); - CanonName = *MD5NameBuffer.insert(FGUID).first; - } - return &Profiles[CanonName]; - } - /// Return the samples collected for function \p F. virtual FunctionSamples *getSamplesFor(StringRef Fname) { std::string FGUID; diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h --- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h +++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h @@ -265,6 +265,11 @@ /// Profile reader object. std::unique_ptr Reader; + /// Synthetic samples created by duplicating the samples of inlined functions + /// from the original profile as if they were top level sample profiles. + /// Use std::map because insertion may happen while its content is referenced. + std::map OutlineFunctionSamples; + // A pseudo probe helper to correlate the imported sample counts. std::unique_ptr ProbeManager; diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -1619,7 +1619,12 @@ // Note that we have to do the merge right after processing function. // This allows OutlineFS's profile to be used for annotation during // top-down processing of functions' annotation. - FunctionSamples *OutlineFS = Reader->getOrCreateSamplesFor(*Callee); + FunctionSamples *OutlineFS = Reader->getSamplesFor(*Callee); + // If outlined function does not exist in the profile, add it to a + // separate map so that it does not rehash the original profile. + if (!OutlineFS) + OutlineFS = &OutlineFunctionSamples[ + FunctionSamples::getCanonicalFnName(Callee->getName())]; OutlineFS->merge(*FS, 1); // Set outlined profile to be synthetic to not bias the inliner. OutlineFS->SetContextSynthetic(); @@ -2571,8 +2576,24 @@ if (FunctionSamples::ProfileIsCS) Samples = ContextTracker->getBaseSamplesFor(F); - else + else { Samples = Reader->getSamplesFor(F); + // Try search in previously inlined functions that were split or duplicated + // into base. + if (!Samples) { + StringRef CanonName = FunctionSamples::getCanonicalFnName(F); + auto It = OutlineFunctionSamples.find(CanonName); + if (It != OutlineFunctionSamples.end()) { + Samples = &It->second; + } else if (auto Remapper = Reader->getRemapper()) { + if (auto RemppedName = Remapper->lookUpNameInProfile(CanonName)) { + It = OutlineFunctionSamples.find(*RemppedName); + if (It != OutlineFunctionSamples.end()) + Samples = &It->second; + } + } + } + } if (Samples && !Samples->empty()) return emitAnnotations(F);