Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -217,6 +217,8 @@ FS_ALIAS = 7, // COMBINED_ALIAS: [modid, linkage, offset] FS_COMBINED_ALIAS = 8, + // COMBINED_ORIGINAL_NAME: [original_name_hash] + FS_COMBINED_ORIGINAL_NAME = 9, }; enum MetadataCodes { Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -96,6 +96,11 @@ /// Kind of summary for use in dyn_cast<> et al. SummaryKind Kind; + /// This is the hash of the name of the symbol in the original file. It is + /// identical to the GUID for global symbols, but differs for local since the + /// GUID includes the module level id in the hash. + GlobalValue::GUID OriginalName; + /// \brief Path of module IR containing value's definition, used to locate /// module during importing. /// @@ -128,6 +133,13 @@ public: virtual ~GlobalValueSummary() = default; + /// Returns the hash of the original name, it is identical to the GUID for + /// externally visible symbols, but not for local ones. + GlobalValue::GUID getOriginalName() { return OriginalName; } + + /// Initialize the original name hash in this summary. + void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; } + /// Which kind of summary subclass this is. SummaryKind getSummaryKind() const { return Kind; } Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -452,7 +452,10 @@ // call graph edges read from the function summary from referencing // callees by their ValueId to using the GUID instead, which is how // they are recorded in the summary index being built. - DenseMap ValueIdToCallGraphGUIDMap; + // We save a second GUID which is the same as the first one, but ignoring the + // linkage, i.e. for value other than local linkage they are identical. + DenseMap> + ValueIdToCallGraphGUIDMap; /// Map to save the association between summary offset in the VST to the /// GlobalValueInfo object created when parsing it. Used to access the @@ -508,7 +511,8 @@ std::error_code initStream(std::unique_ptr Streamer); std::error_code initStreamFromBuffer(); std::error_code initLazyStream(std::unique_ptr Streamer); - GlobalValue::GUID getGUIDFromValueId(unsigned ValueId); + std::pair + getGUIDFromValueId(unsigned ValueId); GlobalValueInfo *getInfoFromSummaryOffset(uint64_t Offset); }; } // end anonymous namespace @@ -5518,7 +5522,7 @@ void ModuleSummaryIndexBitcodeReader::releaseBuffer() { Buffer.release(); } -GlobalValue::GUID +std::pair ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) { auto VGI = ValueIdToCallGraphGUIDMap.find(ValueId); assert(VGI != ValueIdToCallGraphGUIDMap.end()); @@ -5582,13 +5586,19 @@ auto VLI = ValueIdToLinkageMap.find(ValueID); assert(VLI != ValueIdToLinkageMap.end() && "No linkage found for VST entry?"); - std::string GlobalId = GlobalValue::getGlobalIdentifier( - ValueName, VLI->second, SourceFileName); + auto Linkage = VLI->second; + std::string GlobalId = + GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName); auto ValueGUID = GlobalValue::getGUID(GlobalId); + auto OriginalNameID = ValueGUID; + if (GlobalValue::isLocalLinkage(Linkage)) + OriginalNameID = GlobalValue::getGUID(ValueName); if (PrintSummaryGUIDs) - dbgs() << "GUID " << ValueGUID << " is " << ValueName << "\n"; + dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is " + << ValueName << "\n"; TheIndex->addGlobalValueInfo(ValueGUID, std::move(GlobalValInfo)); - ValueIdToCallGraphGUIDMap[ValueID] = ValueGUID; + ValueIdToCallGraphGUIDMap[ValueID] = + std::make_pair(ValueGUID, OriginalNameID); ValueName.clear(); break; } @@ -5604,13 +5614,19 @@ auto VLI = ValueIdToLinkageMap.find(ValueID); assert(VLI != ValueIdToLinkageMap.end() && "No linkage found for VST entry?"); + auto Linkage = VLI->second; std::string FunctionGlobalId = GlobalValue::getGlobalIdentifier( ValueName, VLI->second, SourceFileName); auto FunctionGUID = GlobalValue::getGUID(FunctionGlobalId); + auto OriginalNameID = FunctionGUID; + if (GlobalValue::isLocalLinkage(Linkage)) + OriginalNameID = GlobalValue::getGUID(ValueName); if (PrintSummaryGUIDs) - dbgs() << "GUID " << FunctionGUID << " is " << ValueName << "\n"; + dbgs() << "GUID " << FunctionGUID << "(" << OriginalNameID << ") is " + << ValueName << "\n"; TheIndex->addGlobalValueInfo(FunctionGUID, std::move(FuncInfo)); - ValueIdToCallGraphGUIDMap[ValueID] = FunctionGUID; + ValueIdToCallGraphGUIDMap[ValueID] = + std::make_pair(FunctionGUID, OriginalNameID); ValueName.clear(); break; @@ -5624,14 +5640,15 @@ llvm::make_unique(GlobalValSummaryOffset); SummaryOffsetToInfoMap[GlobalValSummaryOffset] = GlobalValInfo.get(); TheIndex->addGlobalValueInfo(GlobalValGUID, std::move(GlobalValInfo)); - ValueIdToCallGraphGUIDMap[ValueID] = GlobalValGUID; + ValueIdToCallGraphGUIDMap[ValueID] = + std::make_pair(GlobalValGUID, GlobalValGUID); break; } case bitc::VST_CODE_COMBINED_ENTRY: { // VST_CODE_COMBINED_ENTRY: [valueid, refguid] unsigned ValueID = Record[0]; GlobalValue::GUID RefGUID = Record[1]; - ValueIdToCallGraphGUIDMap[ValueID] = RefGUID; + ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(RefGUID, RefGUID); break; } } @@ -5795,7 +5812,9 @@ return error("Invalid record"); SmallVector Record; - + // Keep around the last seen summary to be used when we see an optional + // "OriginalName" attachement. + GlobalValueSummary *LastSeenSummary = nullptr; bool Combined = false; while (1) { BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); @@ -5860,7 +5879,7 @@ "Record size inconsistent with number of references"); for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) { unsigned RefValueId = Record[I]; - GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId); + GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first; FS->addRefEdge(RefGUID); } bool HasProfile = (BitCode == bitc::FS_PERMODULE_PROFILE); @@ -5869,12 +5888,13 @@ unsigned CalleeValueId = Record[I]; unsigned CallsiteCount = Record[++I]; uint64_t ProfileCount = HasProfile ? Record[++I] : 0; - GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId); + GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId).first; FS->addCallGraphEdge(CalleeGUID, CalleeInfo(CallsiteCount, ProfileCount)); } - GlobalValue::GUID GUID = getGUIDFromValueId(ValueID); - auto *Info = TheIndex->getGlobalValueInfo(GUID); + auto GUID = getGUIDFromValueId(ValueID); + FS->setOriginalName(GUID.second); + auto *Info = TheIndex->getGlobalValueInfo(GUID.first); assert(!Info->summary() && "Expected a single summary per VST entry"); Info->setSummary(std::move(FS)); break; @@ -5896,13 +5916,13 @@ AS->setModulePath( TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)->first()); - GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID); + GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID).first; auto *AliaseeInfo = TheIndex->getGlobalValueInfo(AliaseeGUID); if (!AliaseeInfo->summary()) return error("Alias expects aliasee summary to be parsed"); AS->setAliasee(AliaseeInfo->summary()); - GlobalValue::GUID GUID = getGUIDFromValueId(ValueID); + GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first; auto *Info = TheIndex->getGlobalValueInfo(GUID); assert(!Info->summary() && "Expected a single summary per VST entry"); Info->setSummary(std::move(AS)); @@ -5918,10 +5938,10 @@ TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)->first()); for (unsigned I = 2, E = Record.size(); I != E; ++I) { unsigned RefValueId = Record[I]; - GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId); + GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first; FS->addRefEdge(RefGUID); } - GlobalValue::GUID GUID = getGUIDFromValueId(ValueID); + GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first; auto *Info = TheIndex->getGlobalValueInfo(GUID); assert(!Info->summary() && "Expected a single summary per VST entry"); Info->setSummary(std::move(FS)); @@ -5940,6 +5960,7 @@ unsigned NumRefs = Record[3]; std::unique_ptr FS = llvm::make_unique( getDecodedLinkage(RawLinkage), InstCount); + LastSeenSummary = FS.get(); FS->setModulePath(ModuleIdMap[ModuleId]); static int RefListStartIndex = 4; int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs; @@ -5947,7 +5968,7 @@ "Record size inconsistent with number of references"); for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) { unsigned RefValueId = Record[I]; - GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId); + GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first; FS->addRefEdge(RefGUID); } bool HasProfile = (BitCode == bitc::FS_COMBINED_PROFILE); @@ -5956,7 +5977,7 @@ unsigned CalleeValueId = Record[I]; unsigned CallsiteCount = Record[++I]; uint64_t ProfileCount = HasProfile ? Record[++I] : 0; - GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId); + GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId).first; FS->addCallGraphEdge(CalleeGUID, CalleeInfo(CallsiteCount, ProfileCount)); } @@ -5975,6 +5996,7 @@ uint64_t AliaseeSummaryOffset = Record[2]; std::unique_ptr AS = llvm::make_unique(getDecodedLinkage(RawLinkage)); + LastSeenSummary = AS.get(); AS->setModulePath(ModuleIdMap[ModuleId]); auto *AliaseeInfo = getInfoFromSummaryOffset(AliaseeSummaryOffset); @@ -5994,10 +6016,11 @@ uint64_t RawLinkage = Record[1]; std::unique_ptr FS = llvm::make_unique(getDecodedLinkage(RawLinkage)); + LastSeenSummary = FS.get(); FS->setModulePath(ModuleIdMap[ModuleId]); for (unsigned I = 2, E = Record.size(); I != E; ++I) { unsigned RefValueId = Record[I]; - GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId); + GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first; FS->addRefEdge(RefGUID); } auto *Info = getInfoFromSummaryOffset(CurRecordBit); @@ -6006,6 +6029,15 @@ Combined = true; break; } + // FS_COMBINED_ORIGINAL_NAME: [original_name] + case bitc::FS_COMBINED_ORIGINAL_NAME: { + uint64_t OriginalName = Record[0]; + if (!LastSeenSummary) + return error("Name attachment that does not follow a combined record"); + LastSeenSummary->setOriginalName(OriginalName); + // Reset the LastSeenSummary + LastSeenSummary = nullptr; + } } } llvm_unreachable("Exit infinite loop"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3212,6 +3212,17 @@ DenseMap SummaryToOffsetMap; SmallVector NameVals; + + // For local linkage, we also emit the original name separately + // immediately after the record. + auto MaybeEmitOriginalName = [&](GlobalValueSummary &S) { + if (GlobalValue::isLocalLinkage(S.linkage())) { + NameVals.push_back(S.getOriginalName()); + stream().EmitRecord(bitc::FS_COMBINED_ORIGINAL_NAME, NameVals); + NameVals.clear(); + } + }; + for (const auto &FII : *Index) { for (auto &FI : FII.second) { GlobalValueSummary *S = FI->summary(); @@ -3242,6 +3253,7 @@ stream().EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals, FSModRefsAbbrev); NameVals.clear(); + MaybeEmitOriginalName(*S); continue; } @@ -3290,6 +3302,7 @@ // Emit the finished record. stream().EmitRecord(Code, NameVals, FSAbbrev); NameVals.clear(); + MaybeEmitOriginalName(*S); } } @@ -3310,6 +3323,7 @@ // Emit the finished record. stream().EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev); NameVals.clear(); + MaybeEmitOriginalName(*AS); } stream().ExitBlock(); Index: test/Bitcode/thinlto-function-summary-originalnames.ll =================================================================== --- /dev/null +++ test/Bitcode/thinlto-function-summary-originalnames.ll @@ -0,0 +1,20 @@ +; Test to check the callgraph in summary +; RUN: opt -module-summary %s -o %t.o +; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t.o +; RUN: llvm-bcanalyzer -dump %t.index.bc | FileCheck %s --check-prefix=COMBINED + +; COMBINED: +; COMBINED-NEXT: +; COMBINED-NEXT: +; COMBINED-NEXT: + +; ModuleID = 'thinlto-function-summary-callgraph.ll' +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo() { + ret void +} \ No newline at end of file Index: tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp =================================================================== --- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -308,6 +308,7 @@ STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS) STRINGIFY_CODE(FS, ALIAS) STRINGIFY_CODE(FS, COMBINED_ALIAS) + STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME) } case bitc::METADATA_ATTACHMENT_ID: switch(CodeID) {