diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 98df06ae43ad0..cdfee727387a5 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -172,9 +172,11 @@ struct alignas(8) GlobalValueSummaryInfo { /// Add a summary corresponding to a global value definition in a module with /// the corresponding GUID. - void addSummary(std::unique_ptr Summary) { - return SummaryList.push_back(std::move(Summary)); - } + inline void addSummary(std::unique_ptr Summary); + + /// Verify that the HasLocal flag is consistent with the SummaryList. Should + /// only be called prior to index-based internalization and promotion. + inline void verifyLocal() const; private: /// List of global value summary structures for a particular value held @@ -183,6 +185,22 @@ struct alignas(8) GlobalValueSummaryInfo { /// compiling without sufficient distinguishing path, or (theoretically) hash /// collisions. Each summary is from a different module. GlobalValueSummaryList SummaryList; + + /// True if the SummaryList contains at least one summary with local linkage. + /// In most cases there should be only one, unless translation units with + /// same-named locals were compiled without distinguishing path. And generally + /// there should not be a mix of local and non-local summaries, because the + /// GUID for a local is computed with the path prepended and a ';' delimiter. + /// In extremely rare cases there could be a GUID hash collision. Having the + /// flag saves having to walk through all summaries to prove the existence or + /// not of any locals. + /// NOTE: this flag is set when the index is built. It does not reflect + /// index-based internalization and promotion decisions. Generally most + /// index-based analysis occurs before then, but any users should assert that + /// the withInternalizeAndPromote() flag is not set on the index. + /// TODO: Replace checks in various ThinLTO analyses that loop through all + /// summaries to handle the local case with a check of the flag. + bool HasLocal : 1; }; /// Map from global value GUID to corresponding summary structures. Use a @@ -219,6 +237,8 @@ struct ValueInfo { return getRef()->second.getSummaryList(); } + void verifyLocal() const { getRef()->second.verifyLocal(); } + // Even if the index is built with GVs available, we may not have one for // summary entries synthesized for profiled indirect call targets. bool hasName() const { return !haveGVs() || getValue(); } @@ -649,7 +669,23 @@ class GlobalValueSummary { friend class ModuleSummaryIndex; }; -GlobalValueSummaryInfo::GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {} +GlobalValueSummaryInfo::GlobalValueSummaryInfo(bool HaveGVs) + : U(HaveGVs), HasLocal(false) {} + +void GlobalValueSummaryInfo::addSummary( + std::unique_ptr Summary) { + if (GlobalValue::isLocalLinkage(Summary->linkage())) + HasLocal = true; + return SummaryList.push_back(std::move(Summary)); +} + +void GlobalValueSummaryInfo::verifyLocal() const { + assert(HasLocal == + llvm::any_of(SummaryList, + [](const std::unique_ptr &Summary) { + return GlobalValue::isLocalLinkage(Summary->linkage()); + })); +} /// Alias summary information. class AliasSummary : public GlobalValueSummary { diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 72ae064e46a0c..86780e19f22b8 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -477,6 +477,10 @@ static void thinLTOInternalizeAndPromoteGUID( return !GlobalValue::isLocalLinkage(Summary->linkage()); }); + // Before performing index-based internalization and promotion for this GUID, + // the local flag should be consistent with the summary list linkage types. + VI.verifyLocal(); + for (auto &S : VI.getSummaryList()) { // First see if we need to promote an internal value because it is not // exported.