diff options
Diffstat (limited to 'llvm/lib/Bitcode/Reader')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 461 |
1 files changed, 341 insertions, 120 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 06a120a5ff1..4b1ccf85231 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -416,7 +416,7 @@ private: class FunctionIndexBitcodeReader { DiagnosticHandlerFunction DiagnosticHandler; - /// Eventually points to the function index built during parsing. + /// Eventually points to the module index built during parsing. FunctionInfoIndex *TheIndex = nullptr; std::unique_ptr<MemoryBuffer> Buffer; @@ -432,29 +432,37 @@ class FunctionIndexBitcodeReader { bool IsLazy = false; /// Used to indicate whether caller only wants to check for the presence - /// of the function summary bitcode section. All blocks are skipped, - /// but the SeenFuncSummary boolean is set. - bool CheckFuncSummaryPresenceOnly = false; + /// of the global value summary bitcode section. All blocks are skipped, + /// but the SeenGlobalValSummary boolean is set. + bool CheckGlobalValSummaryPresenceOnly = false; - /// Indicates whether we have encountered a function summary section - /// yet during parsing, used when checking if file contains function + /// Indicates whether we have encountered a global value summary section + /// yet during parsing, used when checking if file contains global value /// summary section. - bool SeenFuncSummary = false; + bool SeenGlobalValSummary = false; - /// \brief Map populated during function summary section parsing, and - /// consumed during ValueSymbolTable parsing. - /// - /// Used to correlate summary records with VST entries. For the per-module - /// index this maps the ValueID to the parsed function summary, and - /// for the combined index this maps the summary record's bitcode - /// offset to the function summary (since in the combined index the - /// VST records do not hold value IDs but rather hold the function - /// summary record offset). - DenseMap<uint64_t, std::unique_ptr<FunctionSummary>> SummaryMap; + /// Indicates whether we have already parsed the VST, used for error checking. + bool SeenValueSymbolTable = false; + + /// Set to the offset of the VST recorded in the MODULE_CODE_VSTOFFSET record. + /// Used to enable on-demand parsing of the VST. + uint64_t VSTOffset = 0; + + // Map to save ValueId to GUID association that was recorded in the + // ValueSymbolTable. It is used after the VST is parsed to convert + // 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 function index being built. + DenseMap<unsigned, uint64_t> ValueIdToCallGraphGUIDMap; + + /// Map to save the association between summary offset in the VST to the + /// GlobalValueInfo object created when parsing it. Used to access the + /// info object when parsing the summary section. + DenseMap<uint64_t, GlobalValueInfo *> SummaryOffsetToInfoMap; /// Map populated during module path string table parsing, from the /// module ID to a string reference owned by the index's module - /// path string table, used to correlate with combined index function + /// path string table, used to correlate with combined index /// summary records. DenseMap<uint64_t, StringRef> ModuleIdMap; @@ -469,37 +477,41 @@ public: FunctionIndexBitcodeReader(MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy = false, - bool CheckFuncSummaryPresenceOnly = false); + bool CheckGlobalValSummaryPresenceOnly = false); FunctionIndexBitcodeReader(DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy = false, - bool CheckFuncSummaryPresenceOnly = false); + bool CheckGlobalValSummaryPresenceOnly = false); ~FunctionIndexBitcodeReader() { freeState(); } void freeState(); void releaseBuffer(); - /// Check if the parser has encountered a function summary section. - bool foundFuncSummary() { return SeenFuncSummary; } + /// Check if the parser has encountered a summary section. + bool foundGlobalValSummary() { return SeenGlobalValSummary; } /// \brief Main interface to parsing a bitcode buffer. /// \returns true if an error occurred. std::error_code parseSummaryIndexInto(std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I); - /// \brief Interface for parsing a function summary lazily. + /// \brief Interface for parsing a summary lazily. std::error_code parseFunctionSummary(std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I, size_t FunctionSummaryOffset); private: std::error_code parseModule(); - std::error_code parseValueSymbolTable(); + std::error_code parseValueSymbolTable( + uint64_t Offset, + DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap); std::error_code parseEntireSummary(); std::error_code parseModuleStringTable(); std::error_code initStream(std::unique_ptr<DataStreamer> Streamer); std::error_code initStreamFromBuffer(); std::error_code initLazyStream(std::unique_ptr<DataStreamer> Streamer); + uint64_t getGUIDFromValueId(unsigned ValueId); + GlobalValueInfo *getInfoFromSummaryOffset(uint64_t Offset); }; } // end anonymous namespace @@ -1727,6 +1739,27 @@ ErrorOr<Value *> BitcodeReader::recordValue(SmallVectorImpl<uint64_t> &Record, return V; } +/// Helper to note and return the current location, and jump to the given +/// offset. +static uint64_t jumpToValueSymbolTable(uint64_t Offset, + BitstreamCursor &Stream) { + // Save the current parsing location so we can jump back at the end + // of the VST read. + uint64_t CurrentBit = Stream.GetCurrentBitNo(); + Stream.JumpToBit(Offset * 32); +#ifndef NDEBUG + // Do some checking if we are in debug mode. + BitstreamEntry Entry = Stream.advance(); + assert(Entry.Kind == BitstreamEntry::SubBlock); + assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID); +#else + // In NDEBUG mode ignore the output so we don't get an unused variable + // warning. + Stream.advance(); +#endif + return CurrentBit; +} + /// Parse the value symbol table at either the current parsing location or /// at the given bit offset if provided. std::error_code BitcodeReader::parseValueSymbolTable(uint64_t Offset) { @@ -1734,22 +1767,8 @@ std::error_code BitcodeReader::parseValueSymbolTable(uint64_t Offset) { // Pass in the Offset to distinguish between calling for the module-level // VST (where we want to jump to the VST offset) and the function-level // VST (where we don't). - if (Offset > 0) { - // Save the current parsing location so we can jump back at the end - // of the VST read. - CurrentBit = Stream.GetCurrentBitNo(); - Stream.JumpToBit(Offset * 32); -#ifndef NDEBUG - // Do some checking if we are in debug mode. - BitstreamEntry Entry = Stream.advance(); - assert(Entry.Kind == BitstreamEntry::SubBlock); - assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID); -#else - // In NDEBUG mode ignore the output so we don't get an unused variable - // warning. - Stream.advance(); -#endif - } + if (Offset > 0) + CurrentBit = jumpToValueSymbolTable(Offset, Stream); // Compute the delta between the bitcode indices in the VST (the word offset // to the word-aligned ENTER_SUBBLOCK for the function block, and that @@ -5411,27 +5430,45 @@ std::error_code FunctionIndexBitcodeReader::error(BitcodeError E) { FunctionIndexBitcodeReader::FunctionIndexBitcodeReader( MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler, - bool IsLazy, bool CheckFuncSummaryPresenceOnly) + bool IsLazy, bool CheckGlobalValSummaryPresenceOnly) : DiagnosticHandler(DiagnosticHandler), Buffer(Buffer), IsLazy(IsLazy), - CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {} + CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {} FunctionIndexBitcodeReader::FunctionIndexBitcodeReader( DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy, - bool CheckFuncSummaryPresenceOnly) + bool CheckGlobalValSummaryPresenceOnly) : DiagnosticHandler(DiagnosticHandler), Buffer(nullptr), IsLazy(IsLazy), - CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {} + CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {} void FunctionIndexBitcodeReader::freeState() { Buffer = nullptr; } void FunctionIndexBitcodeReader::releaseBuffer() { Buffer.release(); } -// Specialized value symbol table parser used when reading function index +uint64_t FunctionIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) { + auto VGI = ValueIdToCallGraphGUIDMap.find(ValueId); + assert(VGI != ValueIdToCallGraphGUIDMap.end()); + return VGI->second; +} + +GlobalValueInfo * +FunctionIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) { + auto I = SummaryOffsetToInfoMap.find(Offset); + assert(I != SummaryOffsetToInfoMap.end()); + return I->second; +} + +// Specialized value symbol table parser used when reading module index // blocks where we don't actually create global values. -// At the end of this routine the function index is populated with a map -// from function name to FunctionInfo. The function info contains -// the function block's bitcode offset as well as the offset into the -// function summary section. -std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() { +// At the end of this routine the module index is populated with a map +// from global value name to GlobalValueInfo. The global value info contains +// the function block's bitcode offset (if applicable), or the offset into the +// summary section for the combined index. +std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable( + uint64_t Offset, + DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap) { + assert(Offset > 0 && "Expected non-zero VST offset"); + uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream); + if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID)) return error("Invalid record"); @@ -5447,6 +5484,8 @@ std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() { case BitstreamEntry::Error: return error("Malformed block"); case BitstreamEntry::EndBlock: + // Done parsing VST, jump back to wherever we came from. + Stream.JumpToBit(CurrentBit); return std::error_code(); case BitstreamEntry::Record: // The interesting case. @@ -5458,6 +5497,23 @@ std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() { switch (Stream.readRecord(Entry.ID, Record)) { default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY records). break; + case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N] + if (convertToString(Record, 1, ValueName)) + return error("Invalid record"); + unsigned ValueID = Record[0]; + std::unique_ptr<GlobalValueInfo> GlobalValInfo = + llvm::make_unique<GlobalValueInfo>(); + assert(!SourceFileName.empty()); + auto VLI = ValueIdToLinkageMap.find(ValueID); + assert(VLI != ValueIdToLinkageMap.end() && + "No linkage found for VST entry?"); + std::string GlobalId = + Function::getGlobalIdentifier(ValueName, VLI->second, SourceFileName); + TheIndex->addGlobalValueInfo(GlobalId, std::move(GlobalValInfo)); + ValueIdToCallGraphGUIDMap[ValueID] = Function::getGUID(GlobalId); + ValueName.clear(); + break; + } case bitc::VST_CODE_FNENTRY: { // VST_CODE_FNENTRY: [valueid, offset, namechar x N] if (convertToString(Record, 2, ValueName)) @@ -5465,59 +5521,58 @@ std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() { unsigned ValueID = Record[0]; uint64_t FuncOffset = Record[1]; assert(!IsLazy && "Lazy summary read only supported for combined index"); - // Gracefully handle bitcode without a function summary section, - // which will simply not populate the index. - if (foundFuncSummary()) { - DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI = - SummaryMap.find(ValueID); - assert(SMI != SummaryMap.end() && "Summary info not found"); - std::unique_ptr<FunctionInfo> FuncInfo = - llvm::make_unique<FunctionInfo>(FuncOffset); - FuncInfo->setFunctionSummary(std::move(SMI->second)); - assert(!SourceFileName.empty()); - std::string FunctionGlobalId = Function::getGlobalIdentifier( - ValueName, FuncInfo->functionSummary()->getFunctionLinkage(), - SourceFileName); - TheIndex->addFunctionInfo(FunctionGlobalId, std::move(FuncInfo)); - } + std::unique_ptr<GlobalValueInfo> FuncInfo = + llvm::make_unique<GlobalValueInfo>(FuncOffset); + assert(!SourceFileName.empty()); + auto VLI = ValueIdToLinkageMap.find(ValueID); + assert(VLI != ValueIdToLinkageMap.end() && + "No linkage found for VST entry?"); + std::string FunctionGlobalId = + Function::getGlobalIdentifier(ValueName, VLI->second, SourceFileName); + TheIndex->addGlobalValueInfo(FunctionGlobalId, std::move(FuncInfo)); + ValueIdToCallGraphGUIDMap[ValueID] = Function::getGUID(FunctionGlobalId); ValueName.clear(); break; } - case bitc::VST_CODE_COMBINED_FNENTRY: { - // VST_CODE_COMBINED_FNENTRY: [offset, funcguid] - uint64_t FuncSummaryOffset = Record[0]; - uint64_t FuncGUID = Record[1]; - std::unique_ptr<FunctionInfo> FuncInfo = - llvm::make_unique<FunctionInfo>(FuncSummaryOffset); - if (foundFuncSummary() && !IsLazy) { - DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI = - SummaryMap.find(FuncSummaryOffset); - assert(SMI != SummaryMap.end() && "Summary info not found"); - FuncInfo->setFunctionSummary(std::move(SMI->second)); - } - TheIndex->addFunctionInfo(FuncGUID, std::move(FuncInfo)); - - ValueName.clear(); + case bitc::VST_CODE_COMBINED_GVDEFENTRY: { + // VST_CODE_COMBINED_GVDEFENTRY: [valueid, offset, guid] + unsigned ValueID = Record[0]; + uint64_t GlobalValSummaryOffset = Record[1]; + uint64_t GlobalValGUID = Record[2]; + std::unique_ptr<GlobalValueInfo> GlobalValInfo = + llvm::make_unique<GlobalValueInfo>(GlobalValSummaryOffset); + SummaryOffsetToInfoMap[GlobalValSummaryOffset] = GlobalValInfo.get(); + TheIndex->addGlobalValueInfo(GlobalValGUID, std::move(GlobalValInfo)); + ValueIdToCallGraphGUIDMap[ValueID] = GlobalValGUID; + break; + } + case bitc::VST_CODE_COMBINED_ENTRY: { + // VST_CODE_COMBINED_ENTRY: [valueid, refguid] + unsigned ValueID = Record[0]; + uint64_t RefGUID = Record[1]; + ValueIdToCallGraphGUIDMap[ValueID] = RefGUID; break; } } } } -// Parse just the blocks needed for function index building out of the module. -// At the end of this routine the function Index is populated with a map -// from function name to FunctionInfo. The function info contains -// either the parsed function summary information (when parsing summaries -// eagerly), or just to the function summary record's offset +// Parse just the blocks needed for building the index out of the module. +// At the end of this routine the module Index is populated with a map +// from global value name to GlobalValueInfo. The global value info contains +// either the parsed summary information (when parsing summaries +// eagerly), or just to the summary record's offset // if parsing lazily (IsLazy). std::error_code FunctionIndexBitcodeReader::parseModule() { if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) return error("Invalid record"); SmallVector<uint64_t, 64> Record; + DenseMap<unsigned, GlobalValue::LinkageTypes> ValueIdToLinkageMap; + unsigned ValueId = 0; - // Read the function index for this module. + // Read the index for this module. while (1) { BitstreamEntry Entry = Stream.advance(); @@ -5528,9 +5583,9 @@ std::error_code FunctionIndexBitcodeReader::parseModule() { return std::error_code(); case BitstreamEntry::SubBlock: - if (CheckFuncSummaryPresenceOnly) { - if (Entry.ID == bitc::FUNCTION_SUMMARY_BLOCK_ID) { - SeenFuncSummary = true; + if (CheckGlobalValSummaryPresenceOnly) { + if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID) { + SeenGlobalValSummary = true; // No need to parse the rest since we found the summary. return std::error_code(); } @@ -5549,11 +5604,23 @@ std::error_code FunctionIndexBitcodeReader::parseModule() { return error("Malformed block"); break; case bitc::VALUE_SYMTAB_BLOCK_ID: - if (std::error_code EC = parseValueSymbolTable()) - return EC; + // Should have been parsed earlier via VSTOffset, unless there + // is no summary section. + assert(((SeenValueSymbolTable && VSTOffset > 0) || + !SeenGlobalValSummary) && + "Expected early VST parse via VSTOffset record"); + if (Stream.SkipBlock()) + return error("Invalid record"); break; - case bitc::FUNCTION_SUMMARY_BLOCK_ID: - SeenFuncSummary = true; + case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: + assert(VSTOffset > 0 && "Expected non-zero VST offset"); + assert(!SeenValueSymbolTable && + "Already read VST when parsing summary block?"); + if (std::error_code EC = + parseValueSymbolTable(VSTOffset, ValueIdToLinkageMap)) + return EC; + SeenValueSymbolTable = true; + SeenGlobalValSummary = true; if (IsLazy) { // Lazy parsing of summary info, skip it. if (Stream.SkipBlock()) @@ -5569,8 +5636,8 @@ std::error_code FunctionIndexBitcodeReader::parseModule() { continue; case BitstreamEntry::Record: - // Once we find the single record of interest, skip the rest. - if (!SourceFileName.empty()) + // Once we find the last record of interest, skip the rest. + if (VSTOffset > 0) Stream.skipRecord(Entry.ID); else { Record.clear(); @@ -5579,28 +5646,68 @@ std::error_code FunctionIndexBitcodeReader::parseModule() { default: break; // Default behavior, ignore unknown content. /// MODULE_CODE_SOURCE_FILENAME: [namechar x N] - case bitc::MODULE_CODE_SOURCE_FILENAME: + case bitc::MODULE_CODE_SOURCE_FILENAME: { SmallString<128> ValueName; if (convertToString(Record, 0, ValueName)) return error("Invalid record"); SourceFileName = ValueName.c_str(); break; } + /// MODULE_CODE_VSTOFFSET: [offset] + case bitc::MODULE_CODE_VSTOFFSET: + if (Record.size() < 1) + return error("Invalid record"); + VSTOffset = Record[0]; + break; + // GLOBALVAR: [pointer type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal, + // unnamed_addr, externally_initialized, dllstorageclass, + // comdat] + case bitc::MODULE_CODE_GLOBALVAR: { + if (Record.size() < 6) + return error("Invalid record"); + uint64_t RawLinkage = Record[3]; + GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage); + ValueIdToLinkageMap[ValueId++] = Linkage; + break; + } + // FUNCTION: [type, callingconv, isproto, linkage, paramattr, + // alignment, section, visibility, gc, unnamed_addr, + // prologuedata, dllstorageclass, comdat, prefixdata] + case bitc::MODULE_CODE_FUNCTION: { + if (Record.size() < 8) + return error("Invalid record"); + uint64_t RawLinkage = Record[3]; + GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage); + ValueIdToLinkageMap[ValueId++] = Linkage; + break; + } + // ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility, + // dllstorageclass] + case bitc::MODULE_CODE_ALIAS: { + if (Record.size() < 6) + return error("Invalid record"); + uint64_t RawLinkage = Record[3]; + GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage); + ValueIdToLinkageMap[ValueId++] = Linkage; + break; + } + } } continue; } } } -// Eagerly parse the entire function summary block (i.e. for all functions -// in the index). This populates the FunctionSummary objects in -// the index. +// Eagerly parse the entire summary block. This populates the GlobalValueSummary +// objects in the index. std::error_code FunctionIndexBitcodeReader::parseEntireSummary() { - if (Stream.EnterSubBlock(bitc::FUNCTION_SUMMARY_BLOCK_ID)) + if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID)) return error("Invalid record"); SmallVector<uint64_t, 64> Record; + bool Combined = false; while (1) { BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); @@ -5609,6 +5716,16 @@ std::error_code FunctionIndexBitcodeReader::parseEntireSummary() { case BitstreamEntry::Error: return error("Malformed block"); case BitstreamEntry::EndBlock: + // For a per-module index, remove any entries that still have empty + // summaries. The VST parsing creates entries eagerly for all symbols, + // but not all have associated summaries (e.g. it doesn't know how to + // distinguish between VST_CODE_ENTRY for function declarations vs global + // variables with initializers that end up with a summary). Remove those + // entries now so that we don't need to rely on the combined index merger + // to clean them up (especially since that may not run for the first + // module's index if we merge into that). + if (!Combined) + TheIndex->removeEmptySummaryEntries(); return std::error_code(); case BitstreamEntry::Record: // The interesting case. @@ -5624,17 +5741,23 @@ std::error_code FunctionIndexBitcodeReader::parseEntireSummary() { // information used for ThinLTO renaming and importing. Record.clear(); uint64_t CurRecordBit = Stream.GetCurrentBitNo(); - switch (Stream.readRecord(Entry.ID, Record)) { + auto BitCode = Stream.readRecord(Entry.ID, Record); + switch (BitCode) { default: // Default behavior: ignore. break; - // FS_PERMODULE_ENTRY: [valueid, linkage, instcount] - case bitc::FS_CODE_PERMODULE_ENTRY: { + // FS_PERMODULE: [valueid, linkage, instcount, numrefs, numrefs x valueid, + // n x (valueid, callsitecount)] + // FS_PERMODULE_PROFILE: [valueid, linkage, instcount, numrefs, + // numrefs x valueid, + // n x (valueid, callsitecount, profilecount)] + case bitc::FS_PERMODULE: + case bitc::FS_PERMODULE_PROFILE: { unsigned ValueID = Record[0]; uint64_t RawLinkage = Record[1]; unsigned InstCount = Record[2]; - std::unique_ptr<FunctionSummary> FS = - llvm::make_unique<FunctionSummary>(InstCount); - FS->setFunctionLinkage(getDecodedLinkage(RawLinkage)); + unsigned NumRefs = Record[3]; + std::unique_ptr<FunctionSummary> FS = llvm::make_unique<FunctionSummary>( + getDecodedLinkage(RawLinkage), InstCount); // The module path string ref set in the summary must be owned by the // index's module string table. Since we don't have a module path // string table section in the per-module index, we create a single @@ -5642,19 +5765,115 @@ std::error_code FunctionIndexBitcodeReader::parseEntireSummary() { // ownership. FS->setModulePath( TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)); - SummaryMap[ValueID] = std::move(FS); + static int RefListStartIndex = 4; + int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs; + assert(Record.size() >= RefListStartIndex + NumRefs && + "Record size inconsistent with number of references"); + for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) { + unsigned RefValueId = Record[I]; + uint64_t RefGUID = getGUIDFromValueId(RefValueId); + FS->addRefEdge(RefGUID); + } + bool HasProfile = (BitCode == bitc::FS_PERMODULE_PROFILE); + for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E; + ++I) { + unsigned CalleeValueId = Record[I]; + unsigned CallsiteCount = Record[++I]; + uint64_t ProfileCount = HasProfile ? Record[++I] : 0; + uint64_t CalleeGUID = getGUIDFromValueId(CalleeValueId); + FS->addCallGraphEdge(CalleeGUID, + CalleeInfo(CallsiteCount, ProfileCount)); + } + uint64_t GUID = getGUIDFromValueId(ValueID); + auto InfoList = TheIndex->findGlobalValueInfoList(GUID); + assert(InfoList != TheIndex->end() && + "Expected VST parse to create GlobalValueInfo entry"); + assert(InfoList->second.size() == 1 && + "Expected a single GlobalValueInfo per GUID in module"); + auto &Info = InfoList->second[0]; + assert(!Info->summary() && "Expected a single summary per VST entry"); + Info->setSummary(std::move(FS)); + break; + } + // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, linkage, n x valueid] + case bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS: { + unsigned ValueID = Record[0]; + uint64_t RawLinkage = Record[1]; + std::unique_ptr<GlobalVarSummary> FS = + llvm::make_unique<GlobalVarSummary>(getDecodedLinkage(RawLinkage)); + FS->setModulePath( + TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)); + for (unsigned I = 2, E = Record.size(); I != E; ++I) { + unsigned RefValueId = Record[I]; + uint64_t RefGUID = getGUIDFromValueId(RefValueId); + FS->addRefEdge(RefGUID); + } + uint64_t GUID = getGUIDFromValueId(ValueID); + auto InfoList = TheIndex->findGlobalValueInfoList(GUID); + assert(InfoList != TheIndex->end() && + "Expected VST parse to create GlobalValueInfo entry"); + assert(InfoList->second.size() == 1 && + "Expected a single GlobalValueInfo per GUID in module"); + auto &Info = InfoList->second[0]; + assert(!Info->summary() && "Expected a single summary per VST entry"); + Info->setSummary(std::move(FS)); + break; + } + // FS_COMBINED: [modid, linkage, instcount, numrefs, numrefs x valueid, + // n x (valueid, callsitecount)] + // FS_COMBINED_PROFILE: [modid, linkage, instcount, numrefs, + // numrefs x valueid, + // n x (valueid, callsitecount, profilecount)] + case bitc::FS_COMBINED: + case bitc::FS_COMBINED_PROFILE: { + uint64_t ModuleId = Record[0]; + uint64_t RawLinkage = Record[1]; + unsigned InstCount = Record[2]; + unsigned NumRefs = Record[3]; + std::unique_ptr<FunctionSummary> FS = llvm::make_unique<FunctionSummary>( + getDecodedLinkage(RawLinkage), InstCount); + FS->setModulePath(ModuleIdMap[ModuleId]); + static int RefListStartIndex = 4; + int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs; + assert(Record.size() >= RefListStartIndex + NumRefs && + "Record size inconsistent with number of references"); + for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) { + unsigned RefValueId = Record[I]; + uint64_t RefGUID = getGUIDFromValueId(RefValueId); + FS->addRefEdge(RefGUID); + } + bool HasProfile = (BitCode == bitc::FS_COMBINED_PROFILE); + for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E; + ++I) { + unsigned CalleeValueId = Record[I]; + unsigned CallsiteCount = Record[++I]; + uint64_t ProfileCount = HasProfile ? Record[++I] : 0; + uint64_t CalleeGUID = getGUIDFromValueId(CalleeValueId); + FS->addCallGraphEdge(CalleeGUID, + CalleeInfo(CallsiteCount, ProfileCount)); + } + auto *Info = getInfoFromSummaryOffset(CurRecordBit); + assert(!Info->summary() && "Expected a single summary per VST entry"); + Info->setSummary(std::move(FS)); + Combined = true; break; } - // FS_COMBINED_ENTRY: [modid, linkage, instcount] - case bitc::FS_CODE_COMBINED_ENTRY: { + // FS_COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid] + case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS: { uint64_t ModuleId = Record[0]; uint64_t RawLinkage = Record[1]; - unsigned InstCount = Record[2]; - std::unique_ptr<FunctionSummary> FS = - llvm::make_unique<FunctionSummary>(InstCount); - FS->setFunctionLinkage(getDecodedLinkage(RawLinkage)); + std::unique_ptr<GlobalVarSummary> FS = + llvm::make_unique<GlobalVarSummary>(getDecodedLinkage(RawLinkage)); FS->setModulePath(ModuleIdMap[ModuleId]); - SummaryMap[CurRecordBit] = std::move(FS); + for (unsigned I = 2, E = Record.size(); I != E; ++I) { + unsigned RefValueId = Record[I]; + uint64_t RefGUID = getGUIDFromValueId(RefValueId); + FS->addRefEdge(RefGUID); + } + auto *Info = getInfoFromSummaryOffset(CurRecordBit); + assert(!Info->summary() && "Expected a single summary per VST entry"); + Info->setSummary(std::move(FS)); + Combined = true; break; } } @@ -5773,7 +5992,9 @@ std::error_code FunctionIndexBitcodeReader::parseFunctionSummary( // importing is added so that it can be tested. SmallVector<uint64_t, 64> Record; switch (Stream.readRecord(Entry.ID, Record)) { - case bitc::FS_CODE_COMBINED_ENTRY: + case bitc::FS_COMBINED: + case bitc::FS_COMBINED_PROFILE: + case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS: default: return error("Invalid record"); } @@ -5987,9 +6208,9 @@ llvm::getFunctionInfoIndex(MemoryBufferRef Buffer, return std::move(Index); } -// Check if the given bitcode buffer contains a function summary block. -bool llvm::hasFunctionSummary(MemoryBufferRef Buffer, - DiagnosticHandlerFunction DiagnosticHandler) { +// Check if the given bitcode buffer contains a global value summary block. +bool llvm::hasGlobalValueSummary(MemoryBufferRef Buffer, + DiagnosticHandlerFunction DiagnosticHandler) { std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false); FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, false, true); @@ -6002,7 +6223,7 @@ bool llvm::hasFunctionSummary(MemoryBufferRef Buffer, return cleanupOnError(EC); Buf.release(); // The FunctionIndexBitcodeReader owns it now. - return R.foundFuncSummary(); + return R.foundGlobalValSummary(); } // This method supports lazy reading of function summary data from the combined @@ -6026,7 +6247,7 @@ std::error_code llvm::readFunctionSummary( // contain a list of function infos in the case of a COMDAT. Walk through // and parse each function summary info at the function summary offset // recorded when parsing the value symbol table. - for (const auto &FI : Index->getFunctionInfoList(FunctionName)) { + for (const auto &FI : Index->getGlobalValueInfoList(FunctionName)) { size_t FunctionSummaryOffset = FI->bitcodeIndex(); if (std::error_code EC = R.parseFunctionSummary(nullptr, Index.get(), FunctionSummaryOffset)) |