Index: include/llvm/ProfileData/InstrProf.h =================================================================== --- include/llvm/ProfileData/InstrProf.h +++ include/llvm/ProfileData/InstrProf.h @@ -156,6 +156,10 @@ std::string getPGOFuncName(const Function &F, uint64_t Version = INSTR_PROF_INDEX_VERSION); +/// Return the modified name for function \c F suitable to be +/// used the key for profile lookup in LTO compilation. +std::string getPGOFuncNameInLTO(const Function &F); + /// Return the modified name for a function suitable to be /// used the key for profile lookup. The function's original /// name is \c RawFuncName and has linkage of type \c Linkage. @@ -318,7 +322,7 @@ /// A wrapper interface to populate the PGO symtab with functions /// decls from module \c M. This interface is used by transformation /// passes such as indirect function call promotion. - void create(const Module &M); + void create(const Module &M, bool InLTO = false); /// Create InstrProfSymtab from a set of names iteratable from /// \p IterRange. This interface is used by IndexedProfReader. template void create(const NameIterRange &IterRange); Index: lib/ProfileData/InstrProf.cpp =================================================================== --- lib/ProfileData/InstrProf.cpp +++ lib/ProfileData/InstrProf.cpp @@ -88,6 +88,29 @@ Version); } +// Return the PGOFuncName when called in LTO optimization. LTO's +// internalization privatizes many global linkage symbols into internal linkage. +// This happens after value profile annotation so those internal linkage +// function should have have a source prefix. However, we still need to +// differentiate these symbols from the ones not from LTO's internalization: +// In profile-use, we create a function meta-data if the PGOfuncName is +// different from it's raw name. Use that name if it's available. Otherwise, +// just strip off the source module prefix. +std::string getPGOFuncNameInLTO(const Function &F) { + // First check if these is a metadata. + MDNode *MD = F.getMetadata("PGOFuncName"); + if (MD != nullptr) { + StringRef S = cast(MD->getOperand(0))->getString(); + return S.str(); + } + // Strip out prefix from the the internalized symbols. + std::string PGOName = getPGOFuncName(F); + size_t S = PGOName.find_first_of(':'); + if (S == std::string::npos) + return PGOName; + return PGOName.substr(S + 1); +} + StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) { if (FileName.empty()) return PGOFuncName; @@ -148,9 +171,16 @@ return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName); } -void InstrProfSymtab::create(const Module &M) { - for (const Function &F : M) - addFuncName(getPGOFuncName(F)); +void InstrProfSymtab::create(const Module &M, bool InLTO) { + for (const Function &F : M) { + // Function may not have a name. Ingore in this case. + if (!F.hasName()) + continue; + if (InLTO) + addFuncName(getPGOFuncNameInLTO(F)); + else + addFuncName(getPGOFuncName(F)); + } finalizeSymtab(); } Index: lib/Transforms/Instrumentation/PGOInstrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -246,6 +246,11 @@ BlockFrequencyInfo *BFI = nullptr) : F(Func), FunctionHash(0), MST(F, BPI, BFI) { FuncName = getPGOFuncName(F); + if (FuncName != Func.getName()) { + LLVMContext &C = F.getContext(); + MDNode *N = MDNode::get(C, MDString::get(C, FuncName.c_str())); + F.setMetadata("PGOFuncName", N); + } computeCFGHash(); DEBUG(dumpInfo("after CFGMST"));