Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -28,6 +28,7 @@ #include namespace llvm { +class FunctionInfoIndex; class FunctionType; class GVMaterializer; class LLVMContext; @@ -173,6 +174,7 @@ ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. DataLayout DL; ///< DataLayout associated with the module + std::unique_ptr FunctionIndex; friend class Constant; @@ -639,6 +641,12 @@ /// \brief Set the PIC level (small or large model) void setPICLevel(PICLevel::Level PL); /// @} + + /// Sets the function index for importing into this module. + void setFunctionIndex(std::unique_ptr FI); + + /// Retrieves the function index for importing into this module, if any. + FunctionInfoIndex *getFunctionIndex() const { return FunctionIndex.get(); } }; /// An raw_ostream inserter for modules. Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -86,6 +86,7 @@ (void) llvm::createDomViewerPass(); (void) llvm::createGCOVProfilerPass(); (void) llvm::createInstrProfilingPass(); + (void) llvm::createFunctionImportPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); Index: include/llvm/Linker/Linker.h =================================================================== --- include/llvm/Linker/Linker.h +++ include/llvm/Linker/Linker.h @@ -90,10 +90,12 @@ static bool LinkModules(Module *Dest, Module *Src, DiagnosticHandlerFunction DiagnosticHandler, - unsigned Flags = Flags::None); + unsigned Flags = Flags::None, + FunctionInfoIndex *Index = nullptr); static bool LinkModules(Module *Dest, Module *Src, - unsigned Flags = Flags::None); + unsigned Flags = Flags::None, + FunctionInfoIndex *Index = nullptr); private: void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); Index: include/llvm/Transforms/IPO.h =================================================================== --- include/llvm/Transforms/IPO.h +++ include/llvm/Transforms/IPO.h @@ -86,6 +86,10 @@ deleteFn = false); //===----------------------------------------------------------------------===// +/// This pass performs iterative function importing from other modules. +ModulePass *createFunctionImportPass(); + +//===----------------------------------------------------------------------===// /// createFunctionInliningPass - Return a new pass object that uses a heuristic /// to inline direct function calls to small functions. /// Index: include/llvm/Transforms/IPO/PassManagerBuilder.h =================================================================== --- include/llvm/Transforms/IPO/PassManagerBuilder.h +++ include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H #define LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H +#include #include namespace llvm { @@ -127,6 +128,7 @@ bool VerifyOutput; bool MergeFunctions; bool PrepareForLTO; + bool ImportFunctions; private: /// ExtensionList - This is list of all of the extensions that are registered. Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ lib/IR/Module.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/FunctionInfo.h" #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/LLVMContext.h" @@ -491,3 +492,8 @@ void Module::setPICLevel(PICLevel::Level PL) { addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL); } + +void Module::setFunctionIndex(std::unique_ptr FI) { + assert(!FunctionIndex && "Module already has a FunctionIndex"); + FunctionIndex = std::move(FI); +} Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -2113,14 +2113,15 @@ /// relied on to be consistent. bool Linker::LinkModules(Module *Dest, Module *Src, DiagnosticHandlerFunction DiagnosticHandler, - unsigned Flags) { + unsigned Flags, FunctionInfoIndex *Index) { Linker L(Dest, DiagnosticHandler); - return L.linkInModule(Src, Flags); + return L.linkInModule(Src, Flags, Index); } -bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Flags) { +bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Flags, + FunctionInfoIndex *Index) { Linker L(Dest); - return L.linkInModule(Src, Flags); + return L.linkInModule(Src, Flags, Index); } //===----------------------------------------------------------------------===// Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -239,23 +239,34 @@ /// Pass that performs cross-module function import provided a summary file. class FunctionImportPass : public ModulePass { - public: /// Pass identification, replacement for typeid static char ID; + /// Specify pass name for debug output + const char *getPassName() const override { + return "Function Importing"; + } + explicit FunctionImportPass() : ModulePass(ID) {} bool runOnModule(Module &M) override { - if (SummaryFile.empty()) { - report_fatal_error("error: -function-import requires -summary-file\n"); - } - std::string Error; - std::unique_ptr Index = - getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler); - if (!Index) { - errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n"; - return false; + std::unique_ptr Index(M.getFunctionIndex()); + if (SummaryFile.empty() && !Index) + report_fatal_error("error: -function-import requires -summary-file or " + "file from frontend\n"); + if (!SummaryFile.empty()) { + if (Index) + report_fatal_error("error: -summary-file and index from frontend\n"); + std::string Error; + std::unique_ptr IndexPtr = + getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler); + if (!IndexPtr) { + errs() << "Error loading file '" << SummaryFile << "': " << Error + << "\n"; + return false; + } + Index = std::move(IndexPtr); } // Perform the import now. Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -476,6 +476,9 @@ // Provide AliasAnalysis services for optimizations. addInitialAliasAnalysisPasses(PM); + if (ImportFunctions) + PM.add(createFunctionImportPass()); + // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function // pointers passed as arguments to direct uses of functions.