#define LLVM_LTO_LTO_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
namespace llvm {
return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true);
}
};
+
+
+/// Resolve Weak and LinkOnce values in the \p Index. Linkage changes recorded
+/// in the index and the ThinLTO backends must apply the changes to the Module
+/// via thinLTOResolveWeakForLinkerModule.
+///
+/// This is done for correctness (if value exported, ensure we always
+/// emit a copy), and compile-time optimization (allow drop of duplicates).
+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);
+
+/// Update the linkages in the given \p Index to mark exported values
+/// as external and non-exported values as internal. The ThinLTO backends
+/// must apply the changes to the Module via thinLTOInternalizeModule.
+void thinLTOInternalizeAndPromoteInIndex(
+ ModuleSummaryIndex &Index,
+ std::function<bool(StringRef, GlobalValue::GUID)> isExported);
+
}
#endif
std::error_code
EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
const StringMap<FunctionImporter::ImportMapTy> &ImportLists);
+
+/// Resolve WeakForLinker values in \p TheModule based on the information
+/// recorded in the summaries during global summary-based analysis.
+void thinLTOResolveWeakForLinkerModule(Module &TheModule,
+ const GVSummaryMapTy &DefinedGlobals);
+
+/// Internalize \p TheModule based on the information recorded in the summaries
+/// during global summary-based analysis.
+void thinLTOInternalizeModule(Module &TheModule,
+ const GVSummaryMapTy &DefinedGlobals);
}
#endif // LLVM_FUNCTIONIMPORT_H
}
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);
+}
}
}
}
-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);
-}
-
-/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
-void thinLTOResolveWeakForLinkerModule(Module &TheModule,
- const GVSummaryMapTy &DefinedGlobals) {
- auto updateLinkage = [&](GlobalValue &GV) {
- if (!GlobalValue::isWeakForLinker(GV.getLinkage()))
- return;
- // See if the global summary analysis computed a new resolved linkage.
- const auto &GS = DefinedGlobals.find(GV.getGUID());
- if (GS == DefinedGlobals.end())
- return;
- auto NewLinkage = GS->second->linkage();
- if (NewLinkage == GV.getLinkage())
- return;
- DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
- << GV.getLinkage() << " to " << NewLinkage << "\n");
- GV.setLinkage(NewLinkage);
- };
-
- // Process functions and global now
- for (auto &GV : TheModule)
- updateLinkage(GV);
- for (auto &GV : TheModule.globals())
- updateLinkage(GV);
- for (auto &GV : TheModule.aliases())
- updateLinkage(GV);
-}
-
static StringMap<MemoryBufferRef>
generateModuleMap(const std::vector<MemoryBufferRef> &Modules) {
StringMap<MemoryBufferRef> ModuleMap;
PM.run(TheModule);
}
-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);
-}
-
-// Run internalization on \p TheModule based on symmary analysis.
-void thinLTOInternalizeModule(Module &TheModule,
- const GVSummaryMapTy &DefinedGlobals) {
- // Parse inline ASM and collect the list of symbols that are not defined in
- // the current module.
- StringSet<> AsmUndefinedRefs;
- object::IRObjectFile::CollectAsmUndefinedRefs(
- Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(),
- [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
- if (Flags & object::BasicSymbolRef::SF_Undefined)
- AsmUndefinedRefs.insert(Name);
- });
-
- // Declare a callback for the internalize pass that will ask for every
- // candidate GlobalValue if it can be internalized or not.
- auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
- // Can't be internalized if referenced in inline asm.
- if (AsmUndefinedRefs.count(GV.getName()))
- return true;
-
- // Lookup the linkage recorded in the summaries during global analysis.
- const auto &GS = DefinedGlobals.find(GV.getGUID());
- GlobalValue::LinkageTypes Linkage;
- if (GS == DefinedGlobals.end()) {
- // Must have been promoted (possibly conservatively). Find original
- // name so that we can access the correct summary and see if it can
- // be internalized again.
- // FIXME: Eventually we should control promotion instead of promoting
- // and internalizing again.
- StringRef OrigName =
- ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
- std::string OrigId = GlobalValue::getGlobalIdentifier(
- OrigName, GlobalValue::InternalLinkage,
- TheModule.getSourceFileName());
- const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
- assert(GS != DefinedGlobals.end());
- Linkage = GS->second->linkage();
- } else
- Linkage = GS->second->linkage();
- return !GlobalValue::isLocalLinkage(Linkage);
- };
-
- // FIXME: See if we can just internalize directly here via linkage changes
- // based on the index, rather than invoking internalizeModule.
- llvm::internalizeModule(TheModule, MustPreserveGV);
-}
-
// Convert the PreservedSymbols map from "Name" based to "GUID" based.
static DenseSet<GlobalValue::GUID>
computeGUIDPreservedSymbols(const StringSet<> &PreservedSymbols,
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
+#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#define DEBUG_TYPE "function-import"
return std::error_code();
}
+/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
+void llvm::thinLTOResolveWeakForLinkerModule(
+ Module &TheModule, const GVSummaryMapTy &DefinedGlobals) {
+ auto updateLinkage = [&](GlobalValue &GV) {
+ if (!GlobalValue::isWeakForLinker(GV.getLinkage()))
+ return;
+ // See if the global summary analysis computed a new resolved linkage.
+ const auto &GS = DefinedGlobals.find(GV.getGUID());
+ if (GS == DefinedGlobals.end())
+ return;
+ auto NewLinkage = GS->second->linkage();
+ if (NewLinkage == GV.getLinkage())
+ return;
+ DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
+ << GV.getLinkage() << " to " << NewLinkage << "\n");
+ GV.setLinkage(NewLinkage);
+ };
+
+ // Process functions and global now
+ for (auto &GV : TheModule)
+ updateLinkage(GV);
+ for (auto &GV : TheModule.globals())
+ updateLinkage(GV);
+ for (auto &GV : TheModule.aliases())
+ updateLinkage(GV);
+}
+
+/// Run internalization on \p TheModule based on symmary analysis.
+void llvm::thinLTOInternalizeModule(Module &TheModule,
+ const GVSummaryMapTy &DefinedGlobals) {
+ // Parse inline ASM and collect the list of symbols that are not defined in
+ // the current module.
+ StringSet<> AsmUndefinedRefs;
+ object::IRObjectFile::CollectAsmUndefinedRefs(
+ Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(),
+ [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
+ if (Flags & object::BasicSymbolRef::SF_Undefined)
+ AsmUndefinedRefs.insert(Name);
+ });
+
+ // Declare a callback for the internalize pass that will ask for every
+ // candidate GlobalValue if it can be internalized or not.
+ auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
+ // Can't be internalized if referenced in inline asm.
+ if (AsmUndefinedRefs.count(GV.getName()))
+ return true;
+
+ // Lookup the linkage recorded in the summaries during global analysis.
+ const auto &GS = DefinedGlobals.find(GV.getGUID());
+ GlobalValue::LinkageTypes Linkage;
+ if (GS == DefinedGlobals.end()) {
+ // Must have been promoted (possibly conservatively). Find original
+ // name so that we can access the correct summary and see if it can
+ // be internalized again.
+ // FIXME: Eventually we should control promotion instead of promoting
+ // and internalizing again.
+ StringRef OrigName =
+ ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
+ std::string OrigId = GlobalValue::getGlobalIdentifier(
+ OrigName, GlobalValue::InternalLinkage,
+ TheModule.getSourceFileName());
+ const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
+ assert(GS != DefinedGlobals.end());
+ Linkage = GS->second->linkage();
+ } else
+ Linkage = GS->second->linkage();
+ return !GlobalValue::isLocalLinkage(Linkage);
+ };
+
+ // FIXME: See if we can just internalize directly here via linkage changes
+ // based on the index, rather than invoking internalizeModule.
+ llvm::internalizeModule(TheModule, MustPreserveGV);
+}
+
// Automatically import functions in Module \p DestModule based on the summaries
// index.
//