diff options
author | Teresa Johnson <tejohnson@google.com> | 2016-02-10 18:11:31 +0000 |
---|---|---|
committer | Teresa Johnson <tejohnson@google.com> | 2016-02-10 18:11:31 +0000 |
commit | 488a800a4cf59dc27101aa81c698128ad8c8d354 (patch) | |
tree | 6e4a88a690e4a0dcf50e598cc4423c10d2165280 /llvm/lib/Linker/LinkModules.cpp | |
parent | ee195caf661f009f7c0733fb58ace98e350cc2e8 (diff) | |
download | bcm5719-llvm-488a800a4cf59dc27101aa81c698128ad8c8d354.tar.gz bcm5719-llvm-488a800a4cf59dc27101aa81c698128ad8c8d354.zip |
[ThinLTO] Move global processing from Linker to TransformUtils (NFC)
Summary:
As discussed on IRC, move the ThinLTOGlobalProcessing code out of
the linker, and into TransformUtils. The name of the class is changed
to FunctionImportGlobalProcessing.
Reviewers: joker.eph, rafael
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17081
llvm-svn: 260395
Diffstat (limited to 'llvm/lib/Linker/LinkModules.cpp')
-rw-r--r-- | llvm/lib/Linker/LinkModules.cpp | 300 |
1 files changed, 6 insertions, 294 deletions
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index 4bb4b3f4f23..b96a6f42705 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -11,13 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Linker/Linker.h" #include "LinkDiagnosticInfo.h" #include "llvm-c/Linker.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringSet.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Transforms/Utils/FunctionImportUtils.h" using namespace llvm; namespace { @@ -141,257 +142,13 @@ public: bool run(); }; - -/// Class to handle necessary GlobalValue changes required by ThinLTO including -/// linkage changes and any necessary renaming. -class ThinLTOGlobalProcessing { - /// The Module which we are exporting or importing functions from. - Module &M; - - /// Function index passed in for function importing/exporting handling. - const FunctionInfoIndex *ImportIndex; - - /// Functions to import from this module, all other functions will be - /// imported as declarations instead of definitions. - DenseSet<const GlobalValue *> *FunctionsToImport; - - /// Set to true if the given FunctionInfoIndex contains any functions - /// from this source module, in which case we must conservatively assume - /// that any of its functions may be imported into another module - /// as part of a different backend compilation process. - bool HasExportedFunctions = false; - - /// Populated during ThinLTO global processing with locals promoted - /// to global scope in an exporting module, which now need to be linked - /// in if calling from the ModuleLinker. - SetVector<GlobalValue *> NewExportedValues; - - /// Check if we should promote the given local value to global scope. - bool doPromoteLocalToGlobal(const GlobalValue *SGV); - - /// Helper methods to check if we are importing from or potentially - /// exporting from the current source module. - bool isPerformingImport() const { return FunctionsToImport != nullptr; } - bool isModuleExporting() const { return HasExportedFunctions; } - - /// If we are importing from the source module, checks if we should - /// import SGV as a definition, otherwise import as a declaration. - bool doImportAsDefinition(const GlobalValue *SGV); - - /// Get the name for SGV that should be used in the linked destination - /// module. Specifically, this handles the case where we need to rename - /// a local that is being promoted to global scope. - std::string getName(const GlobalValue *SGV); - - /// Process globals so that they can be used in ThinLTO. This includes - /// promoting local variables so that they can be reference externally by - /// thin lto imported globals and converting strong external globals to - /// available_externally. - void processGlobalsForThinLTO(); - void processGlobalForThinLTO(GlobalValue &GV); - - /// Get the new linkage for SGV that should be used in the linked destination - /// module. Specifically, for ThinLTO importing or exporting it may need - /// to be adjusted. - GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV); - -public: - ThinLTOGlobalProcessing( - Module &M, const FunctionInfoIndex *Index, - DenseSet<const GlobalValue *> *FunctionsToImport = nullptr) - : M(M), ImportIndex(Index), FunctionsToImport(FunctionsToImport) { - // If we have a FunctionInfoIndex but no function to import, - // then this is the primary module being compiled in a ThinLTO - // backend compilation, and we need to see if it has functions that - // may be exported to another backend compilation. - if (!FunctionsToImport) - HasExportedFunctions = ImportIndex->hasExportedFunctions(M); - } - - bool run(); - - /// Access the promoted globals that are now exported and need to be linked. - SetVector<GlobalValue *> &getNewExportedValues() { return NewExportedValues; } -}; -} - -/// Checks if we should import SGV as a definition, otherwise import as a -/// declaration. -static bool -doImportAsDefinitionImpl(const GlobalValue *SGV, - DenseSet<const GlobalValue *> *FunctionsToImport) { - auto *GA = dyn_cast<GlobalAlias>(SGV); - if (GA) { - if (GA->hasWeakAnyLinkage()) - return false; - const GlobalObject *GO = GA->getBaseObject(); - if (!GO->hasLinkOnceODRLinkage()) - return false; - return doImportAsDefinitionImpl(GO, FunctionsToImport); - } - // Always import GlobalVariable definitions, except for the special - // case of WeakAny which are imported as ExternalWeak declarations - // (see comments in ModuleLinker::getLinkage). The linkage changes - // described in ModuleLinker::getLinkage ensure the correct behavior (e.g. - // global variables with external linkage are transformed to - // available_externally definitions, which are ultimately turned into - // declarations after the EliminateAvailableExternally pass). - if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() && - !SGV->hasWeakAnyLinkage()) - return true; - // Only import the function requested for importing. - auto *SF = dyn_cast<Function>(SGV); - if (SF && FunctionsToImport->count(SF)) - return true; - // Otherwise no. - return false; -} - -bool ThinLTOGlobalProcessing::doImportAsDefinition(const GlobalValue *SGV) { - if (!isPerformingImport()) - return false; - return doImportAsDefinitionImpl(SGV, FunctionsToImport); } bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { if (!isPerformingImport()) return false; - return doImportAsDefinitionImpl(SGV, FunctionsToImport); -} - -bool ThinLTOGlobalProcessing::doPromoteLocalToGlobal(const GlobalValue *SGV) { - assert(SGV->hasLocalLinkage()); - // Both the imported references and the original local variable must - // be promoted. - if (!isPerformingImport() && !isModuleExporting()) - return false; - - // Local const variables never need to be promoted unless they are address - // taken. The imported uses can simply use the clone created in this module. - // For now we are conservative in determining which variables are not - // address taken by checking the unnamed addr flag. To be more aggressive, - // the address taken information must be checked earlier during parsing - // of the module and recorded in the function index for use when importing - // from that module. - auto *GVar = dyn_cast<GlobalVariable>(SGV); - if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr()) - return false; - - // Eventually we only need to promote functions in the exporting module that - // are referenced by a potentially exported function (i.e. one that is in the - // function index). - return true; -} - -std::string ThinLTOGlobalProcessing::getName(const GlobalValue *SGV) { - // For locals that must be promoted to global scope, ensure that - // the promoted name uniquely identifies the copy in the original module, - // using the ID assigned during combined index creation. When importing, - // we rename all locals (not just those that are promoted) in order to - // avoid naming conflicts between locals imported from different modules. - if (SGV->hasLocalLinkage() && - (doPromoteLocalToGlobal(SGV) || isPerformingImport())) - return FunctionInfoIndex::getGlobalNameForLocal( - SGV->getName(), - ImportIndex->getModuleId(SGV->getParent()->getModuleIdentifier())); - return SGV->getName(); -} - -GlobalValue::LinkageTypes -ThinLTOGlobalProcessing::getLinkage(const GlobalValue *SGV) { - // Any local variable that is referenced by an exported function needs - // to be promoted to global scope. Since we don't currently know which - // functions reference which local variables/functions, we must treat - // all as potentially exported if this module is exporting anything. - if (isModuleExporting()) { - if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV)) - return GlobalValue::ExternalLinkage; - return SGV->getLinkage(); - } - - // Otherwise, if we aren't importing, no linkage change is needed. - if (!isPerformingImport()) - return SGV->getLinkage(); - - switch (SGV->getLinkage()) { - case GlobalValue::ExternalLinkage: - // External defnitions are converted to available_externally - // definitions upon import, so that they are available for inlining - // and/or optimization, but are turned into declarations later - // during the EliminateAvailableExternally pass. - if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV)) - return GlobalValue::AvailableExternallyLinkage; - // An imported external declaration stays external. - return SGV->getLinkage(); - - case GlobalValue::AvailableExternallyLinkage: - // An imported available_externally definition converts - // to external if imported as a declaration. - if (!doImportAsDefinition(SGV)) - return GlobalValue::ExternalLinkage; - // An imported available_externally declaration stays that way. - return SGV->getLinkage(); - - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - // These both stay the same when importing the definition. - // The ThinLTO pass will eventually force-import their definitions. - return SGV->getLinkage(); - - case GlobalValue::WeakAnyLinkage: - // Can't import weak_any definitions correctly, or we might change the - // program semantics, since the linker will pick the first weak_any - // definition and importing would change the order they are seen by the - // linker. The module linking caller needs to enforce this. - assert(!doImportAsDefinition(SGV)); - // If imported as a declaration, it becomes external_weak. - return GlobalValue::ExternalWeakLinkage; - - case GlobalValue::WeakODRLinkage: - // For weak_odr linkage, there is a guarantee that all copies will be - // equivalent, so the issue described above for weak_any does not exist, - // and the definition can be imported. It can be treated similarly - // to an imported externally visible global value. - if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV)) - return GlobalValue::AvailableExternallyLinkage; - else - return GlobalValue::ExternalLinkage; - - case GlobalValue::AppendingLinkage: - // It would be incorrect to import an appending linkage variable, - // since it would cause global constructors/destructors to be - // executed multiple times. This should have already been handled - // by linkIfNeeded, and we will assert in shouldLinkFromSource - // if we try to import, so we simply return AppendingLinkage. - return GlobalValue::AppendingLinkage; - - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - // If we are promoting the local to global scope, it is handled - // similarly to a normal externally visible global. - if (doPromoteLocalToGlobal(SGV)) { - if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV)) - return GlobalValue::AvailableExternallyLinkage; - else - return GlobalValue::ExternalLinkage; - } - // A non-promoted imported local definition stays local. - // The ThinLTO pass will eventually force-import their definitions. - return SGV->getLinkage(); - - case GlobalValue::ExternalWeakLinkage: - // External weak doesn't apply to definitions, must be a declaration. - assert(!doImportAsDefinition(SGV)); - // Linkage stays external_weak. - return SGV->getLinkage(); - - case GlobalValue::CommonLinkage: - // Linkage stays common on definitions. - // The ThinLTO pass will eventually force-import their definitions. - return SGV->getLinkage(); - } - - llvm_unreachable("unknown linkage type"); + return FunctionImportGlobalProcessing::doImportAsDefinition( + SGV, FunctionsToImport); } static GlobalValue::VisibilityTypes @@ -713,46 +470,6 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add) { } } -void ThinLTOGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { - if (GV.hasLocalLinkage() && - (doPromoteLocalToGlobal(&GV) || isPerformingImport())) { - GV.setName(getName(&GV)); - GV.setLinkage(getLinkage(&GV)); - if (!GV.hasLocalLinkage()) - GV.setVisibility(GlobalValue::HiddenVisibility); - if (isModuleExporting()) - NewExportedValues.insert(&GV); - } else - GV.setLinkage(getLinkage(&GV)); - - // Remove functions imported as available externally defs from comdats, - // as this is a declaration for the linker, and will be dropped eventually. - // It is illegal for comdats to contain declarations. - auto *GO = dyn_cast_or_null<GlobalObject>(&GV); - if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) { - // The IRMover should not have placed any imported declarations in - // a comdat, so the only declaration that should be in a comdat - // at this point would be a definition imported as available_externally. - assert(GO->hasAvailableExternallyLinkage() && - "Expected comdat on definition (possibly available external)"); - GO->setComdat(nullptr); - } -} - -void ThinLTOGlobalProcessing::processGlobalsForThinLTO() { - for (GlobalVariable &GV : M.globals()) - processGlobalForThinLTO(GV); - for (Function &SF : M) - processGlobalForThinLTO(SF); - for (GlobalAlias &GA : M.aliases()) - processGlobalForThinLTO(GA); -} - -bool ThinLTOGlobalProcessing::run() { - processGlobalsForThinLTO(); - return false; -} - bool ModuleLinker::run() { for (const auto &SMEC : SrcM.getComdatSymbolTable()) { const Comdat &C = SMEC.getValue(); @@ -792,8 +509,8 @@ bool ModuleLinker::run() { return true; if (ImportIndex) { - ThinLTOGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex, - FunctionsToImport); + FunctionImportGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex, + FunctionsToImport); if (ThinLTOProcessing.run()) return true; for (auto *GV : ThinLTOProcessing.getNewExportedValues()) @@ -871,11 +588,6 @@ bool Linker::linkModules(Module &Dest, std::unique_ptr<Module> Src, return L.linkInModule(std::move(Src), Flags); } -bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) { - ThinLTOGlobalProcessing ThinLTOProcessing(M, Index); - return ThinLTOProcessing.run(); -} - //===----------------------------------------------------------------------===// // C API. //===----------------------------------------------------------------------===// |