diff options
Diffstat (limited to 'llvm/lib/LTO/LTO.cpp')
-rw-r--r-- | llvm/lib/LTO/LTO.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 5f89e5c95a7..fa875c29e29 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -39,4 +39,104 @@ std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer, } return std::move(ModuleOrErr.get()); } + +static void thinLTOResolveWeakForLinkerGUID( + GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID, + DenseSet<GlobalValueSummary *> &GlobalInvolvedWithAlias, + std::function<bool(GlobalValue::GUID, const GlobalValueSummary *)> + isPrevailing, + std::function<bool(StringRef, GlobalValue::GUID)> isExported, + std::function<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> + recordNewLinkage) { + auto HasMultipleCopies = GVSummaryList.size() > 1; + + for (auto &S : GVSummaryList) { + if (GlobalInvolvedWithAlias.count(S.get())) + continue; + GlobalValue::LinkageTypes OriginalLinkage = S->linkage(); + if (!GlobalValue::isWeakForLinker(OriginalLinkage)) + continue; + // 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 when possible. + if (!HasMultipleCopies) { + // Exported Linkonce needs to be promoted to not be discarded. + // FIXME: This should handle LinkOnceAny as well, but that should be a + // follow-on to the NFC restructuring: + // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage) && + // isExported(S->modulePath(), GUID)) + // S->setLinkage(GlobalValue::getWeakLinkage( + // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))); + if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) && + isExported(S->modulePath(), GUID)) + S->setLinkage(GlobalValue::WeakODRLinkage); + } else if (isPrevailing(GUID, S.get())) { + // FIXME: This should handle LinkOnceAny as well, but that should be a + // follow-on to the NFC restructuring: + // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage)) + // S->setLinkage(GlobalValue::getWeakLinkage( + // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))); + if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)) + S->setLinkage(GlobalValue::WeakODRLinkage); + } + // Alias can't be turned into available_externally. + else if (!isa<AliasSummary>(S.get()) && + (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) || + GlobalValue::isWeakODRLinkage(OriginalLinkage))) + S->setLinkage(GlobalValue::AvailableExternallyLinkage); + if (S->linkage() != OriginalLinkage) + recordNewLinkage(S->modulePath(), GUID, S->linkage()); + } +} + +// Resolve Weak and LinkOnce values in the \p Index. +// +// We'd like to drop these functions if they are no longer referenced in the +// current module. However there is a chance that another module is still +// referencing them because of the import. We make sure we always emit at least +// one copy. +void thinLTOResolveWeakForLinkerInIndex( + ModuleSummaryIndex &Index, + std::function<bool(GlobalValue::GUID, const GlobalValueSummary *)> + isPrevailing, + std::function<bool(StringRef, GlobalValue::GUID)> isExported, + std::function<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> + recordNewLinkage) { + if (Index.modulePaths().size() == 1) + // Nothing to do if we don't have multiple modules + return; + + // We won't optimize the globals that are referenced by an alias for now + // Ideally we should turn the alias into a global and duplicate the definition + // when needed. + DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias; + for (auto &I : Index) + for (auto &S : I.second) + if (auto AS = dyn_cast<AliasSummary>(S.get())) + GlobalInvolvedWithAlias.insert(&AS->getAliasee()); + + for (auto &I : Index) + thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias, + isPrevailing, isExported, recordNewLinkage); +} + +static void thinLTOInternalizeAndPromoteGUID( + GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID, + std::function<bool(StringRef, GlobalValue::GUID)> isExported) { + for (auto &S : GVSummaryList) { + if (isExported(S->modulePath(), GUID)) { + if (GlobalValue::isLocalLinkage(S->linkage())) + S->setLinkage(GlobalValue::ExternalLinkage); + } else if (!GlobalValue::isLocalLinkage(S->linkage())) + S->setLinkage(GlobalValue::InternalLinkage); + } +} + +// Update the linkages in the given \p Index to mark exported values +// as external and non-exported values as internal. +void thinLTOInternalizeAndPromoteInIndex( + ModuleSummaryIndex &Index, + std::function<bool(StringRef, GlobalValue::GUID)> isExported) { + for (auto &I : Index) + thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported); +} } |