Index: llvm/trunk/include/llvm/Analysis/ModuleSummaryAnalysis.h =================================================================== --- llvm/trunk/include/llvm/Analysis/ModuleSummaryAnalysis.h +++ llvm/trunk/include/llvm/Analysis/ModuleSummaryAnalysis.h @@ -47,12 +47,12 @@ std::unique_ptr takeIndex() { return std::move(Index); } private: - /// Compute info for given function with optional frequency information - void computeFunctionInfo(const Function &F, - BlockFrequencyInfo *BFI = nullptr); + /// Compute summary for given function with optional frequency information + void computeFunctionSummary(const Function &F, + BlockFrequencyInfo *BFI = nullptr); - /// Compute info for given variable with optional frequency information - void computeVariableInfo(const GlobalVariable &V); + /// Compute summary for given variable with optional frequency information + void computeVariableSummary(const GlobalVariable &V); }; /// Legacy wrapper pass to provide the ModuleSummaryIndex object. Index: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h @@ -84,9 +84,6 @@ /// \brief Function and variable summary information to aid decisions and /// implementation of importing. -/// -/// This is a separate class from GlobalValueInfo to enable lazy reading of this -/// summary information from the combined index file during imporing. class GlobalValueSummary { public: /// \brief Sububclass discriminator (for dyn_cast<> et al.) @@ -291,67 +288,25 @@ } }; -/// \brief Class to hold pointer to summary object and information required -/// for parsing or writing it. -class GlobalValueInfo { -private: - /// Summary information used to help make ThinLTO importing decisions. - std::unique_ptr Summary; - - /// \brief The bitcode offset corresponding to either an associated - /// function's function body record, or to an associated summary record, - /// depending on whether this is a per-module or combined index. - /// - /// This bitcode offset is written to or read from the associated - /// \a ValueSymbolTable entry for a function. - /// For the per-module index this holds the bitcode offset of a - /// function's body record within bitcode module block in its module, - /// although this field is currently only used when writing the VST - /// (it is set to 0 and also unused when this is a global variable). - /// For the combined index this holds the offset of the corresponding - /// summary record, to enable associating the combined index - /// VST records with the summary records. - uint64_t BitcodeIndex; - -public: - GlobalValueInfo(uint64_t Offset = 0, - std::unique_ptr Summary = nullptr) - : Summary(std::move(Summary)), BitcodeIndex(Offset) {} - - /// Record the summary information parsed out of the summary block during - /// parsing or combined index creation. - void setSummary(std::unique_ptr GVSummary) { - Summary = std::move(GVSummary); - } - - /// Get the summary recorded for this global value. - GlobalValueSummary *summary() const { return Summary.get(); } - - /// Get the bitcode index recorded for this value symbol table entry. - uint64_t bitcodeIndex() const { return BitcodeIndex; } - - /// Set the bitcode index recorded for this value symbol table entry. - void setBitcodeIndex(uint64_t Offset) { BitcodeIndex = Offset; } -}; - /// 160 bits SHA1 typedef std::array ModuleHash; -/// List of global value info structures for a particular value held +/// List of global value summary structures for a particular value held /// in the GlobalValueMap. Requires a vector in the case of multiple /// COMDAT values of the same name. -typedef std::vector> GlobalValueInfoList; +typedef std::vector> GlobalValueSummaryList; -/// Map from global value GUID to corresponding info structures. +/// Map from global value GUID to corresponding summary structures. /// Use a std::map rather than a DenseMap since it will likely incur /// less overhead, as the value type is not very small and the size /// of the map is unknown, resulting in inefficiencies due to repeated /// insertions and resizing. -typedef std::map GlobalValueInfoMapTy; +typedef std::map + GlobalValueSummaryMapTy; -/// Type used for iterating through the global value info map. -typedef GlobalValueInfoMapTy::const_iterator const_globalvalueinfo_iterator; -typedef GlobalValueInfoMapTy::iterator globalvalueinfo_iterator; +/// Type used for iterating through the global value summary map. +typedef GlobalValueSummaryMapTy::const_iterator const_gvsummary_iterator; +typedef GlobalValueSummaryMapTy::iterator gvsummary_iterator; /// String table to hold/own module path strings, which additionally holds the /// module ID assigned to each module during the plugin step, as well as a hash @@ -362,9 +317,9 @@ /// and encapsulate methods for operating on them. class ModuleSummaryIndex { private: - /// Map from value name to list of information instances for values of that + /// Map from value name to list of summary instances for values of that /// name (may be duplicates in the COMDAT case, e.g.). - GlobalValueInfoMapTy GlobalValueMap; + GlobalValueSummaryMapTy GlobalValueMap; /// Holds strings for combined index, mapping to the corresponding module ID. ModulePathStringTableTy ModulePathStringTable; @@ -377,55 +332,55 @@ ModuleSummaryIndex(const ModuleSummaryIndex &) = delete; void operator=(const ModuleSummaryIndex &) = delete; - globalvalueinfo_iterator begin() { return GlobalValueMap.begin(); } - const_globalvalueinfo_iterator begin() const { - return GlobalValueMap.begin(); - } - globalvalueinfo_iterator end() { return GlobalValueMap.end(); } - const_globalvalueinfo_iterator end() const { return GlobalValueMap.end(); } + gvsummary_iterator begin() { return GlobalValueMap.begin(); } + const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } + gvsummary_iterator end() { return GlobalValueMap.end(); } + const_gvsummary_iterator end() const { return GlobalValueMap.end(); } - /// Get the list of global value info objects for a given value name. - const GlobalValueInfoList &getGlobalValueInfoList(StringRef ValueName) { + /// Get the list of global value summary objects for a given value name. + const GlobalValueSummaryList &getGlobalValueSummaryList(StringRef ValueName) { return GlobalValueMap[GlobalValue::getGUID(ValueName)]; } - /// Get the list of global value info objects for a given value name. - const const_globalvalueinfo_iterator - findGlobalValueInfoList(StringRef ValueName) const { + /// Get the list of global value summary objects for a given value name. + const const_gvsummary_iterator + findGlobalValueSummaryList(StringRef ValueName) const { return GlobalValueMap.find(GlobalValue::getGUID(ValueName)); } - /// Get the list of global value info objects for a given value GUID. - const const_globalvalueinfo_iterator - findGlobalValueInfoList(GlobalValue::GUID ValueGUID) const { + /// Get the list of global value summary objects for a given value GUID. + const const_gvsummary_iterator + findGlobalValueSummaryList(GlobalValue::GUID ValueGUID) const { return GlobalValueMap.find(ValueGUID); } - /// Add a global value info for a value of the given name. - void addGlobalValueInfo(StringRef ValueName, - std::unique_ptr Info) { - GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(std::move(Info)); + /// Add a global value summary for a value of the given name. + void addGlobalValueSummary(StringRef ValueName, + std::unique_ptr Summary) { + GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back( + std::move(Summary)); } - /// Add a global value info for a value of the given GUID. - void addGlobalValueInfo(GlobalValue::GUID ValueGUID, - std::unique_ptr Info) { - GlobalValueMap[ValueGUID].push_back(std::move(Info)); + /// Add a global value summary for a value of the given GUID. + void addGlobalValueSummary(GlobalValue::GUID ValueGUID, + std::unique_ptr Summary) { + GlobalValueMap[ValueGUID].push_back(std::move(Summary)); } - /// Returns the first GlobalValueInfo for \p GV, asserting that there + /// Returns the first GlobalValueSummary for \p GV, asserting that there /// is only one if \p PerModuleIndex. - GlobalValueInfo *getGlobalValueInfo(const GlobalValue &GV, - bool PerModuleIndex = true) const { - assert(GV.hasName() && "Can't get GlobalValueInfo for GV with no name"); - return getGlobalValueInfo(GlobalValue::getGUID(GV.getName()), - PerModuleIndex); + GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV, + bool PerModuleIndex = true) const { + assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name"); + return getGlobalValueSummary(GlobalValue::getGUID(GV.getName()), + PerModuleIndex); } - /// Returns the first GlobalValueInfo for \p ValueGUID, asserting that there + /// Returns the first GlobalValueSummary for \p ValueGUID, asserting that + /// there /// is only one if \p PerModuleIndex. - GlobalValueInfo *getGlobalValueInfo(GlobalValue::GUID ValueGUID, - bool PerModuleIndex = true) const; + GlobalValueSummary *getGlobalValueSummary(GlobalValue::GUID ValueGUID, + bool PerModuleIndex = true) const; /// Table of modules, containing module hash and id. const StringMap> &modulePaths() const { @@ -493,7 +448,7 @@ /// (GUID -> Summary). void collectDefinedFunctionsForModule( StringRef ModulePath, - std::map &FunctionInfoMap) const; + std::map &GVSummaryMap) const; /// Collect for each module the list of Summaries it defines (GUID -> /// Summary). Index: llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp +++ llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -61,8 +61,8 @@ } } -void ModuleSummaryIndexBuilder::computeFunctionInfo(const Function &F, - BlockFrequencyInfo *BFI) { +void ModuleSummaryIndexBuilder::computeFunctionSummary( + const Function &F, BlockFrequencyInfo *BFI) { // Summary not currently supported for anonymous functions, they must // be renamed. if (!F.hasName()) @@ -100,12 +100,11 @@ llvm::make_unique(Flags, NumInsts); FuncSummary->addCallGraphEdges(CallGraphEdges); FuncSummary->addRefEdges(RefEdges); - std::unique_ptr GVInfo = - llvm::make_unique(0, std::move(FuncSummary)); - Index->addGlobalValueInfo(F.getName(), std::move(GVInfo)); + Index->addGlobalValueSummary(F.getName(), std::move(FuncSummary)); } -void ModuleSummaryIndexBuilder::computeVariableInfo(const GlobalVariable &V) { +void ModuleSummaryIndexBuilder::computeVariableSummary( + const GlobalVariable &V) { DenseSet RefEdges; SmallPtrSet Visited; findRefEdges(&V, RefEdges, Visited); @@ -113,9 +112,7 @@ std::unique_ptr GVarSummary = llvm::make_unique(Flags); GVarSummary->addRefEdges(RefEdges); - std::unique_ptr GVInfo = - llvm::make_unique(0, std::move(GVarSummary)); - Index->addGlobalValueInfo(V.getName(), std::move(GVInfo)); + Index->addGlobalValueSummary(V.getName(), std::move(GVarSummary)); } ModuleSummaryIndexBuilder::ModuleSummaryIndexBuilder( @@ -164,7 +161,7 @@ BFI = BFIPtr.get(); } - computeFunctionInfo(F, BFI); + computeFunctionSummary(F, BFI); } // Compute summaries for all variables defined in module, and save in the @@ -172,7 +169,7 @@ for (const GlobalVariable &G : M->globals()) { if (G.isDeclaration()) continue; - computeVariableInfo(G); + computeVariableSummary(G); } } Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -493,9 +493,9 @@ 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 SummaryOffsetToInfoMap; + /// GUID created when parsing it. Used to add newly parsed summaries to + /// the index. + DenseMap SummaryOffsetToGUIDMap; /// Map populated during module path string table parsing, from the /// module ID to a string reference owned by the index's module @@ -548,7 +548,7 @@ std::error_code initLazyStream(std::unique_ptr Streamer); std::pair getGUIDFromValueId(unsigned ValueId); - GlobalValueInfo *getInfoFromSummaryOffset(uint64_t Offset); + GlobalValue::GUID getGUIDFromOffset(uint64_t Offset); }; } // end anonymous namespace @@ -5736,19 +5736,16 @@ return VGI->second; } -GlobalValueInfo * -ModuleSummaryIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) { - auto I = SummaryOffsetToInfoMap.find(Offset); - assert(I != SummaryOffsetToInfoMap.end()); +GlobalValue::GUID +ModuleSummaryIndexBitcodeReader::getGUIDFromOffset(uint64_t Offset) { + auto I = SummaryOffsetToGUIDMap.find(Offset); + assert(I != SummaryOffsetToGUIDMap.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 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. +// blocks where we don't actually create global values. The parsed information +// is saved in the bitcode reader for use when later parsing summaries. std::error_code ModuleSummaryIndexBitcodeReader::parseValueSymbolTable( uint64_t Offset, DenseMap &ValueIdToLinkageMap) { @@ -5787,8 +5784,6 @@ if (convertToString(Record, 1, ValueName)) return error("Invalid record"); unsigned ValueID = Record[0]; - std::unique_ptr GlobalValInfo = - llvm::make_unique(); assert(!SourceFileName.empty()); auto VLI = ValueIdToLinkageMap.find(ValueID); assert(VLI != ValueIdToLinkageMap.end() && @@ -5803,7 +5798,6 @@ if (PrintSummaryGUIDs) dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is " << ValueName << "\n"; - TheIndex->addGlobalValueInfo(ValueGUID, std::move(GlobalValInfo)); ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(ValueGUID, OriginalNameID); ValueName.clear(); @@ -5814,9 +5808,6 @@ if (convertToString(Record, 2, ValueName)) return error("Invalid record"); unsigned ValueID = Record[0]; - uint64_t FuncOffset = Record[1]; - std::unique_ptr FuncInfo = - llvm::make_unique(FuncOffset); assert(!SourceFileName.empty()); auto VLI = ValueIdToLinkageMap.find(ValueID); assert(VLI != ValueIdToLinkageMap.end() && @@ -5831,7 +5822,6 @@ if (PrintSummaryGUIDs) dbgs() << "GUID " << FunctionGUID << "(" << OriginalNameID << ") is " << ValueName << "\n"; - TheIndex->addGlobalValueInfo(FunctionGUID, std::move(FuncInfo)); ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(FunctionGUID, OriginalNameID); @@ -5843,10 +5833,7 @@ unsigned ValueID = Record[0]; uint64_t GlobalValSummaryOffset = Record[1]; GlobalValue::GUID GlobalValGUID = Record[2]; - std::unique_ptr GlobalValInfo = - llvm::make_unique(GlobalValSummaryOffset); - SummaryOffsetToInfoMap[GlobalValSummaryOffset] = GlobalValInfo.get(); - TheIndex->addGlobalValueInfo(GlobalValGUID, std::move(GlobalValInfo)); + SummaryOffsetToGUIDMap[GlobalValSummaryOffset] = GlobalValGUID; // The "original name", which is the second value of the pair will be // overriden later by a FS_COMBINED_ORIGINAL_NAME in the combined index. ValueIdToCallGraphGUIDMap[ValueID] = @@ -5868,8 +5855,7 @@ // 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 -// the parsed summary information (when parsing summaries eagerly). +// from global value id to GlobalValueSummary objects. std::error_code ModuleSummaryIndexBitcodeReader::parseModule() { if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) return error("Invalid record"); @@ -6040,6 +6026,11 @@ // "OriginalName" attachement. GlobalValueSummary *LastSeenSummary = nullptr; bool Combined = false; + // For aliases in the combined summary, we need to know which summary + // corresponds to the aliasee offset saved in the alias summary. It isn't + // sufficient to just map to the aliasee GUID, since in the combined summary + // there may be multiple values with the same GUID. + DenseMap OffsetToSummaryMap; while (1) { BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); @@ -6119,9 +6110,7 @@ } 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)); + TheIndex->addGlobalValueSummary(GUID.first, std::move(FS)); break; } // FS_ALIAS: [valueid, flags, valueid] @@ -6142,16 +6131,14 @@ TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)->first()); GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID).first; - auto *AliaseeInfo = TheIndex->getGlobalValueInfo(AliaseeGUID); - if (!AliaseeInfo->summary()) + auto *AliaseeSummary = TheIndex->getGlobalValueSummary(AliaseeGUID); + if (!AliaseeSummary) return error("Alias expects aliasee summary to be parsed"); - AS->setAliasee(AliaseeInfo->summary()); + AS->setAliasee(AliaseeSummary); auto GUID = getGUIDFromValueId(ValueID); AS->setOriginalName(GUID.second); - auto *Info = TheIndex->getGlobalValueInfo(GUID.first); - assert(!Info->summary() && "Expected a single summary per VST entry"); - Info->setSummary(std::move(AS)); + TheIndex->addGlobalValueSummary(GUID.first, std::move(AS)); break; } // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, flags, n x valueid] @@ -6170,9 +6157,7 @@ } 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)); + TheIndex->addGlobalValueSummary(GUID.first, std::move(FS)); break; } // FS_COMBINED: [modid, flags, instcount, numrefs, numrefs x valueid, @@ -6210,9 +6195,9 @@ 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)); + GlobalValue::GUID GUID = getGUIDFromOffset(CurRecordBit); + OffsetToSummaryMap[CurRecordBit] = FS.get(); + TheIndex->addGlobalValueSummary(GUID, std::move(FS)); Combined = true; break; } @@ -6228,14 +6213,13 @@ LastSeenSummary = AS.get(); AS->setModulePath(ModuleIdMap[ModuleId]); - auto *AliaseeInfo = getInfoFromSummaryOffset(AliaseeSummaryOffset); - if (!AliaseeInfo->summary()) + auto *AliaseeSummary = OffsetToSummaryMap[AliaseeSummaryOffset]; + if (!AliaseeSummary) return error("Alias expects aliasee summary to be parsed"); - AS->setAliasee(AliaseeInfo->summary()); + AS->setAliasee(AliaseeSummary); - auto *Info = getInfoFromSummaryOffset(CurRecordBit); - assert(!Info->summary() && "Expected a single summary per VST entry"); - Info->setSummary(std::move(AS)); + GlobalValue::GUID GUID = getGUIDFromOffset(CurRecordBit); + TheIndex->addGlobalValueSummary(GUID, std::move(AS)); Combined = true; break; } @@ -6253,9 +6237,9 @@ GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first; FS->addRefEdge(RefGUID); } - auto *Info = getInfoFromSummaryOffset(CurRecordBit); - assert(!Info->summary() && "Expected a single summary per VST entry"); - Info->setSummary(std::move(FS)); + GlobalValue::GUID GUID = getGUIDFromOffset(CurRecordBit); + OffsetToSummaryMap[CurRecordBit] = FS.get(); + TheIndex->addGlobalValueSummary(GUID, std::move(FS)); Combined = true; break; } Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -246,7 +246,7 @@ DenseMap &FunctionToBitcodeIndex); void writeBlockInfo(); void writePerModuleFunctionSummaryRecord(SmallVector &NameVals, - GlobalValueInfo *Info, + GlobalValueSummary *Summary, unsigned ValueID, unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev, @@ -270,6 +270,10 @@ /// Tracks the last value id recorded in the GUIDToValueMap. unsigned GlobalValueId = 0; + /// Record the starting offset of each summary entry for use in the VST + /// entry, and for any possible alias. + DenseMap SummaryToOffsetMap; + public: /// Constructs a IndexBitcodeWriter object for the given combined index, /// writing to the provided \p Buffer. @@ -2639,15 +2643,17 @@ SmallVector NameVals; - for (const auto &FII : Index) { - GlobalValue::GUID FuncGUID = FII.first; - unsigned ValueId = popValueId(FuncGUID); + for (const auto &GSI : Index) { + GlobalValue::GUID ValGUID = GSI.first; + unsigned ValueId = popValueId(ValGUID); - for (const auto &FI : FII.second) { + for (const auto &SI : GSI.second) { // VST_CODE_COMBINED_GVDEFENTRY: [valueid, sumoffset, guid] NameVals.push_back(ValueId); - NameVals.push_back(FI->bitcodeIndex()); - NameVals.push_back(FuncGUID); + auto Offset = SummaryToOffsetMap[SI.get()]; + assert(Offset); + NameVals.push_back(Offset); + NameVals.push_back(ValGUID); // Emit the finished record. Stream.EmitRecord(bitc::VST_CODE_COMBINED_GVDEFENTRY, NameVals, @@ -3031,12 +3037,12 @@ // Helper to emit a single function summary record. void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord( - SmallVector &NameVals, GlobalValueInfo *Info, + SmallVector &NameVals, GlobalValueSummary *Summary, unsigned ValueID, unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev, const Function &F) { NameVals.push_back(ValueID); - FunctionSummary *FS = cast(Info->summary()); + FunctionSummary *FS = cast(Summary); NameVals.push_back(getEncodedGVSummaryFlags(FS->flags())); NameVals.push_back(FS->instCount()); NameVals.push_back(FS->refs().size()); @@ -3072,8 +3078,8 @@ return; NameVals.push_back(VE.getValueID(&V)); NameVals.push_back(getEncodedGVSummaryFlags(V)); - auto *Info = Index->getGlobalValueInfo(V); - GlobalVarSummary *VS = cast(Info->summary()); + auto *Summary = Index->getGlobalValueSummary(V); + GlobalVarSummary *VS = cast(Summary); for (auto Ref : VS->refs()) NameVals.push_back(VE.getValueID(Ref.getValue())); Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals, @@ -3151,9 +3157,9 @@ if (!F.hasName()) report_fatal_error("Unexpected anonymous function when writing summary"); - auto *Info = Index->getGlobalValueInfo(F); + auto *Summary = Index->getGlobalValueSummary(F); writePerModuleFunctionSummaryRecord( - NameVals, Info, + NameVals, Summary, VE.getValueID(M.getValueSymbolTable().lookup(F.getName())), FSCallsAbbrev, FSCallsProfileAbbrev, F); } @@ -3227,10 +3233,8 @@ unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv); // The aliases are emitted as a post-pass, and will point to the summary - // offset id of the aliasee. For this purpose we need to be able to get back - // from the summary to the offset - SmallVector Aliases; - DenseMap SummaryToOffsetMap; + // offset id of the aliasee. Save them in a vector for post-processing. + SmallVector Aliases; SmallVector NameVals; @@ -3244,14 +3248,14 @@ NameVals.clear(); }; - for (const auto &FII : Index) { - for (auto &FI : FII.second) { - GlobalValueSummary *S = FI->summary(); + for (const auto &GSI : Index) { + for (auto &SI : GSI.second) { + GlobalValueSummary *S = SI.get(); assert(S); - if (isa(S)) { + if (auto *AS = dyn_cast(S)) { // Will process aliases as a post-pass because the reader wants all // global to be loaded first. - Aliases.push_back(FI.get()); + Aliases.push_back(AS); continue; } @@ -3262,13 +3266,11 @@ NameVals.push_back(getValueId(RI.getGUID())); } - // Record the starting offset of this summary entry for use - // in the VST entry. Add the current code size since the - // reader will invoke readRecord after the abbrev id read. - FI->setBitcodeIndex(Stream.GetCurrentBitNo() + - Stream.GetAbbrevIDWidth()); - // Store temporarily the offset in the map for a possible alias. - SummaryToOffsetMap[S] = FI->bitcodeIndex(); + // Record the starting offset of this summary entry for use in the VST + // entry, and for any possible alias. Add the current code size since + // the reader will invoke readRecord after the abbrev id read. + SummaryToOffsetMap[S] = + Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth(); // Emit the finished record. Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals, @@ -3307,12 +3309,11 @@ NameVals.push_back(EI.second.ProfileCount); } - // Record the starting offset of this summary entry for use - // in the VST entry. Add the current code size since the - // reader will invoke readRecord after the abbrev id read. - FI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth()); - // Store temporarily the offset in the map for a possible alias. - SummaryToOffsetMap[S] = FI->bitcodeIndex(); + // Record the starting offset of this summary entry for use in the VST + // entry, and for any possible alias. Add the current code size since + // the reader will invoke readRecord after the abbrev id read. + SummaryToOffsetMap[S] = + Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth(); unsigned FSAbbrev = (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev); @@ -3326,8 +3327,7 @@ } } - for (auto GVI : Aliases) { - AliasSummary *AS = cast(GVI->summary()); + for (auto *AS : Aliases) { NameVals.push_back(Index.getModuleId(AS->modulePath())); NameVals.push_back(getEncodedGVSummaryFlags(AS->flags())); auto AliaseeOffset = SummaryToOffsetMap[&AS->getAliasee()]; @@ -3337,7 +3337,8 @@ // Record the starting offset of this summary entry for use // in the VST entry. Add the current code size since the // reader will invoke readRecord after the abbrev id read. - GVI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth()); + SummaryToOffsetMap[AS] = + Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth(); // Emit the finished record. Stream.EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev); Index: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp =================================================================== --- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp +++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp @@ -22,38 +22,34 @@ uint64_t NextModuleId) { StringRef ModPath; - for (auto &OtherGlobalValInfoLists : *Other) { - GlobalValue::GUID ValueGUID = OtherGlobalValInfoLists.first; - GlobalValueInfoList &List = OtherGlobalValInfoLists.second; + for (auto &OtherGlobalValSummaryLists : *Other) { + GlobalValue::GUID ValueGUID = OtherGlobalValSummaryLists.first; + GlobalValueSummaryList &List = OtherGlobalValSummaryLists.second; - // Assert that the value info list only has one entry, since we shouldn't + // Assert that the value summary list only has one entry, since we shouldn't // have duplicate names within a single per-module index. assert(List.size() == 1); - std::unique_ptr Info = std::move(List.front()); - - // Skip if there was no summary section. - if (!Info->summary()) - continue; + std::unique_ptr Summary = std::move(List.front()); // Add the module path string ref for this module if we haven't already // saved a reference to it. if (ModPath.empty()) { - auto Path = Info->summary()->modulePath(); + auto Path = Summary->modulePath(); ModPath = addModulePath(Path, NextModuleId, Other->getModuleHash(Path)) ->first(); } else - assert(ModPath == Info->summary()->modulePath() && + assert(ModPath == Summary->modulePath() && "Each module in the combined map should have a unique ID"); // Note the module path string ref was copied above and is still owned by // the original per-module index. Reset it to the new module path // string reference owned by the combined index. - Info->summary()->setModulePath(ModPath); + Summary->setModulePath(ModPath); - // Add new value info to existing list. There may be duplicates when + // Add new value summary to existing list. There may be duplicates when // combining GlobalValueMap entries, due to COMDAT values. Any local // values were given unique global IDs. - addGlobalValueInfo(ValueGUID, std::move(Info)); + addGlobalValueSummary(ValueGUID, std::move(Summary)); } } @@ -62,7 +58,7 @@ // Only expect this to be called on a per-module index, which has a single // entry per value entry list. assert(MI->second.size() == 1); - if (!MI->second[0]->summary()) + if (!MI->second[0]) MI = GlobalValueMap.erase(MI); else ++MI; @@ -73,42 +69,41 @@ // (GUID -> Summary). void ModuleSummaryIndex::collectDefinedFunctionsForModule( StringRef ModulePath, - std::map &FunctionInfoMap) const { + std::map &GVSummaryMap) const { for (auto &GlobalList : *this) { auto GUID = GlobalList.first; - for (auto &GlobInfo : GlobalList.second) { - auto *Summary = dyn_cast_or_null(GlobInfo->summary()); + for (auto &GlobSummary : GlobalList.second) { + auto *Summary = dyn_cast_or_null(GlobSummary.get()); if (!Summary) // Ignore global variable, focus on functions continue; // Ignore summaries from other modules. if (Summary->modulePath() != ModulePath) continue; - FunctionInfoMap[GUID] = Summary; + GVSummaryMap[GUID] = Summary; } } } // Collect for each module the list of function it defines (GUID -> Summary). void ModuleSummaryIndex::collectDefinedGVSummariesPerModule( - StringMap> & - Module2FunctionInfoMap) const { + StringMap> + &ModuleToDefinedGVSummaries) const { for (auto &GlobalList : *this) { auto GUID = GlobalList.first; - for (auto &GlobInfo : GlobalList.second) { - auto *Summary = GlobInfo->summary(); - Module2FunctionInfoMap[Summary->modulePath()][GUID] = Summary; + for (auto &Summary : GlobalList.second) { + ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); } } } -GlobalValueInfo * -ModuleSummaryIndex::getGlobalValueInfo(uint64_t ValueGUID, - bool PerModuleIndex) const { - auto InfoList = findGlobalValueInfoList(ValueGUID); - assert(InfoList != end() && "GlobalValue not found in index"); - assert((!PerModuleIndex || InfoList->second.size() == 1) && +GlobalValueSummary * +ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID, + bool PerModuleIndex) const { + auto SummaryList = findGlobalValueSummaryList(ValueGUID); + assert(SummaryList != end() && "GlobalValue not found in index"); + assert((!PerModuleIndex || SummaryList->second.size() == 1) && "Expected a single entry per global value in per-module index"); - auto &Info = InfoList->second[0]; - return Info.get(); + auto &Summary = SummaryList->second[0]; + return Summary.get(); } Index: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp +++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp @@ -109,23 +109,24 @@ WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true); } -bool IsFirstDefinitionForLinker(const GlobalValueInfoList &GVInfo, +bool IsFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList, const ModuleSummaryIndex &Index, StringRef ModulePath) { // Get the first *linker visible* definition for this global in the summary // list. auto FirstDefForLinker = llvm::find_if( - GVInfo, [](const std::unique_ptr &FuncInfo) { - auto Linkage = FuncInfo->summary()->linkage(); + GVSummaryList, [](const std::unique_ptr &Summary) { + auto Linkage = Summary->linkage(); return !GlobalValue::isAvailableExternallyLinkage(Linkage); }); // If \p GV is not the first definition, give up... - if ((*FirstDefForLinker)->summary()->modulePath() != ModulePath) + if ((*FirstDefForLinker)->modulePath() != ModulePath) return false; // If there is any strong definition anywhere, do not bother emitting this. if (llvm::any_of( - GVInfo, [](const std::unique_ptr &FuncInfo) { - auto Linkage = FuncInfo->summary()->linkage(); + GVSummaryList, + [](const std::unique_ptr &Summary) { + auto Linkage = Summary->linkage(); return !GlobalValue::isAvailableExternallyLinkage(Linkage) && !GlobalValue::isWeakForLinker(Linkage); })) @@ -138,8 +139,9 @@ const FunctionImporter::ExportSetTy &ExportList, StringRef ModuleIdentifier, GlobalValue::GUID GUID, const GlobalValueSummary &GV) { - auto HasMultipleCopies = - [&](const GlobalValueInfoList &GVInfo) { return GVInfo.size() > 1; }; + auto HasMultipleCopies = [&](const GlobalValueSummaryList &GVSummaryList) { + return GVSummaryList.size() > 1; + }; auto OriginalLinkage = GV.linkage(); switch (OriginalLinkage) { @@ -155,17 +157,17 @@ break; case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakODRLinkage: { - auto &GVInfo = Index.findGlobalValueInfoList(GUID)->second; + auto &GVSummaryList = Index.findGlobalValueSummaryList(GUID)->second; // We need to emit only one of these, the first module will keep // it, but turned into a weak while the others will drop it. - if (!HasMultipleCopies(GVInfo)) { + if (!HasMultipleCopies(GVSummaryList)) { // Exported LinkonceODR needs to be promoted to not be discarded if (GlobalValue::isDiscardableIfUnused(OriginalLinkage) && ExportList.count(GUID)) return GlobalValue::WeakODRLinkage; break; } - if (IsFirstDefinitionForLinker(GVInfo, Index, ModuleIdentifier)) + if (IsFirstDefinitionForLinker(GVSummaryList, Index, ModuleIdentifier)) return GlobalValue::WeakODRLinkage; else if (isa(&GV)) // Alias can't be turned into available_externally. Index: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp +++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp @@ -86,12 +86,12 @@ /// - One that has PGO data attached. /// - [insert you fancy metric here] static const GlobalValueSummary * -selectCallee(const GlobalValueInfoList &CalleeInfoList, unsigned Threshold) { +selectCallee(const GlobalValueSummaryList &CalleeSummaryList, + unsigned Threshold) { auto It = llvm::find_if( - CalleeInfoList, [&](const std::unique_ptr &GlobInfo) { - assert(GlobInfo->summary() && - "We should not have a Global Info without summary"); - auto *GVSummary = GlobInfo->summary(); + CalleeSummaryList, + [&](const std::unique_ptr &SummaryPtr) { + auto *GVSummary = SummaryPtr.get(); if (GlobalValue::isWeakAnyLinkage(GVSummary->linkage())) // There is no point in importing weak symbols, we can't inline them return false; @@ -113,10 +113,10 @@ return true; }); - if (It == CalleeInfoList.end()) + if (It == CalleeSummaryList.end()) return nullptr; - return cast((*It)->summary()); + return cast(It->get()); } /// Return the summary for the function \p GUID that fits the \p Threshold, or @@ -124,11 +124,11 @@ static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID, unsigned Threshold, const ModuleSummaryIndex &Index) { - auto CalleeInfoList = Index.findGlobalValueInfoList(GUID); - if (CalleeInfoList == Index.end()) { + auto CalleeSummaryList = Index.findGlobalValueSummaryList(GUID); + if (CalleeSummaryList == Index.end()) { return nullptr; // This function does not have a summary } - return selectCallee(CalleeInfoList->second, Threshold); + return selectCallee(CalleeSummaryList->second, Threshold); } /// Mark the global \p GUID as export by module \p ExportModulePath if found in @@ -138,32 +138,29 @@ StringRef ExportModulePath, GlobalValue::GUID GUID, FunctionImporter::ExportSetTy &ExportList) { - auto FindGlobalInfoInModule = - [&](GlobalValue::GUID GUID) -> GlobalValueInfo *{ - auto InfoList = Index.findGlobalValueInfoList(GUID); - if (InfoList == Index.end()) + auto FindGlobalSummaryInModule = + [&](GlobalValue::GUID GUID) -> GlobalValueSummary *{ + auto SummaryList = Index.findGlobalValueSummaryList(GUID); + if (SummaryList == Index.end()) // This global does not have a summary, it is not part of the ThinLTO // process return nullptr; - auto Info = llvm::find_if( - InfoList->second, - [&](const std::unique_ptr &GlobInfo) { - auto *Summary = GlobInfo->summary(); - assert(Summary && "Unexpected GlobalValueInfo without summary"); + auto SummaryIter = llvm::find_if( + SummaryList->second, + [&](const std::unique_ptr &Summary) { return Summary->modulePath() == ExportModulePath; }); - if (Info == InfoList->second.end()) + if (SummaryIter == SummaryList->second.end()) return nullptr; - return Info->get(); + return SummaryIter->get(); }; - auto *GVInfo = FindGlobalInfoInModule(GUID); - if (!GVInfo) + auto *Summary = FindGlobalSummaryInModule(GUID); + if (!Summary) return; // We found it in the current module, mark as exported ExportList.insert(GUID); - auto *Summary = GVInfo->summary(); auto GVS = dyn_cast(Summary); if (!GVS) return; @@ -174,8 +171,8 @@ // FIXME: with a "isConstant" flag in the summary we could be more targetted. for (auto &Ref : GVS->refs()) { auto GUID = Ref.getGUID(); - auto *RefInfo = FindGlobalInfoInModule(GUID); - if (RefInfo) + auto *RefSummary = FindGlobalSummaryInModule(GUID); + if (RefSummary) // Found a ref in the current module, mark it as exported ExportList.insert(GUID); } @@ -269,15 +266,15 @@ // Populate the worklist with the import for the functions in the current // module - for (auto &GVInfo : DefinedGVSummaries) { - auto *Summary = GVInfo.second; + for (auto &GVSummary : DefinedGVSummaries) { + auto *Summary = GVSummary.second; if (auto *AS = dyn_cast(Summary)) Summary = &AS->getAliasee(); auto *FuncSummary = dyn_cast(Summary); if (!FuncSummary) // Skip import for global variables continue; - DEBUG(dbgs() << "Initalize import for " << GVInfo.first << "\n"); + DEBUG(dbgs() << "Initalize import for " << GVSummary.first << "\n"); computeImportForFunction(*FuncSummary, Index, ImportInstrLimit, DefinedGVSummaries, Worklist, ImportsForModule, ExportLists); @@ -340,12 +337,12 @@ // Collect the list of functions this module defines. // GUID -> Summary - std::map FunctionInfoMap; - Index.collectDefinedFunctionsForModule(ModulePath, FunctionInfoMap); + std::map FunctionSummaryMap; + Index.collectDefinedFunctionsForModule(ModulePath, FunctionSummaryMap); // Compute the import list for this module. DEBUG(dbgs() << "Computing import for Module '" << ModulePath << "'\n"); - ComputeImportForModule(FunctionInfoMap, Index, ImportList); + ComputeImportForModule(FunctionSummaryMap, Index, ImportList); #ifndef NDEBUG DEBUG(dbgs() << "* Module " << ModulePath << " imports from "