summaryrefslogtreecommitdiffstats
path: root/llvm/lib/LTO/LTO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/LTO/LTO.cpp')
-rw-r--r--llvm/lib/LTO/LTO.cpp100
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);
+}
}
OpenPOWER on IntegriCloud