return Result;
}
-// Get a Module for \p FileName from the cache, or load it lazily.
-Module &FunctionImporter::getOrLoadModule(StringRef FileName) {
- auto &Module = ModuleMap[FileName];
- if (!Module)
- Module = loadFile(FileName, Context);
- return *Module;
-}
-
/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
for (auto &BB : F) {
for (auto &I : BB) {
if (isa<CallInst>(I)) {
- DEBUG(dbgs() << "Found a call: '" << I << "'\n");
auto CalledFunction = cast<CallInst>(I).getCalledFunction();
// Insert any new external calls that have not already been
// added to set/worklist.
}
}
-// Automatically import functions in Module \p M based on the summaries index.
-//
-// The current implementation imports every called functions that exists in the
-// summaries index.
-bool FunctionImporter::importFunctions(Module &M) {
- assert(&Context == &M.getContext());
-
- bool Changed = false;
-
- /// First step is collecting the called external functions.
- StringSet<> CalledFunctions;
- SmallVector<StringRef, 64> Worklist;
- for (auto &F : M) {
- if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
- continue;
- findExternalCalls(F, CalledFunctions, Worklist);
- }
-
- /// Second step: for every call to an external function, try to import it.
-
- // Linker that will be used for importing function
- Linker L(&M, DiagnosticHandler);
-
+// Helper function: given a worklist and an index, will process all the worklist
+// and import them based on the summary information
+static unsigned ProcessImportWorklist(
+ Module &DestModule, SmallVector<StringRef, 64> &Worklist,
+ StringSet<> &CalledFunctions, Linker &TheLinker,
+ const FunctionInfoIndex &Index,
+ std::function<std::unique_ptr<Module>(StringRef FileName)> &
+ LazyModuleLoader) {
+ unsigned ImportCount = 0;
while (!Worklist.empty()) {
auto CalledFunctionName = Worklist.pop_back_val();
- DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");
+ DEBUG(dbgs() << DestModule.getModuleIdentifier() << "Process import for "
+ << CalledFunctionName << "\n");
// Try to get a summary for this function call.
auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
if (InfoList == Index.end()) {
- DEBUG(dbgs() << "No summary for " << CalledFunctionName
- << " Ignoring.\n");
+ DEBUG(dbgs() << DestModule.getModuleIdentifier() << "No summary for "
+ << CalledFunctionName << " Ignoring.\n");
continue;
}
assert(!InfoList->second.empty() && "No summary, error at import?");
auto *Summary = Info->functionSummary();
if (!Summary) {
// FIXME: in case we are lazyloading summaries, we can do it now.
- dbgs() << "Missing summary for " << CalledFunctionName
- << ", error at import?\n";
+ DEBUG(dbgs() << DestModule.getModuleIdentifier()
+ << " Missing summary for " << CalledFunctionName
+ << ", error at import?\n");
llvm_unreachable("Missing summary");
}
if (Summary->instCount() > ImportInstrLimit) {
- dbgs() << "Skip import of " << CalledFunctionName << " with "
- << Summary->instCount() << " instructions (limit "
- << ImportInstrLimit << ")\n";
+ DEBUG(dbgs() << DestModule.getModuleIdentifier() << " Skip import of "
+ << CalledFunctionName << " with " << Summary->instCount()
+ << " instructions (limit " << ImportInstrLimit << ")\n");
continue;
}
DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
<< "\n");
- // Get the module for the import (potentially from the cache).
- auto &Module = getOrLoadModule(FileName);
+ // Get the module for the import
+ auto SrcModule = LazyModuleLoader(FileName);
+ assert(&SrcModule->getContext() == &DestModule.getContext());
// The function that we will import!
- GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
+ GlobalValue *SGV = SrcModule->getNamedValue(CalledFunctionName);
StringRef ImportFunctionName = CalledFunctionName;
if (!SGV) {
- // Might be local in source Module, promoted/renamed in dest Module M.
+ // Might be local in source Module, promoted/renamed in DestModule.
std::pair<StringRef, StringRef> Split =
CalledFunctionName.split(".llvm.");
- SGV = Module.getNamedValue(Split.first);
+ SGV = SrcModule->getNamedValue(Split.first);
#ifndef NDEBUG
// Assert that Split.second is module id
uint64_t ModuleId;
// the order they are seen and selected by the linker, changing program
// semantics.
if (SGV->hasWeakAnyLinkage()) {
- DEBUG(dbgs() << "Ignoring import request for weak-any "
+ DEBUG(dbgs() << DestModule.getModuleIdentifier()
+ << " Ignoring import request for weak-any "
<< (isa<Function>(SGV) ? "function " : "alias ")
<< CalledFunctionName << " from " << FileName << "\n");
continue;
}
// Link in the specified function.
- if (L.linkInModule(&Module, Linker::Flags::None, &Index, F))
+ DenseSet<const GlobalValue *> FunctionsToImport;
+ FunctionsToImport.insert(F);
+ if (TheLinker.linkInModule(*SrcModule, Linker::Flags::None, &Index,
+ &FunctionsToImport))
report_fatal_error("Function Import: link error");
// Process the newly imported function and add callees to the worklist.
- GlobalValue *NewGV = M.getNamedValue(ImportFunctionName);
+ GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName);
assert(NewGV);
Function *NewF = dyn_cast<Function>(NewGV);
assert(NewF);
findExternalCalls(*NewF, CalledFunctions, Worklist);
+ ++ImportCount;
+ }
+ return ImportCount;
+}
- Changed = true;
+// Automatically import functions in Module \p DestModule based on the summaries
+// index.
+//
+// The current implementation imports every called functions that exists in the
+// summaries index.
+bool FunctionImporter::importFunctions(Module &DestModule) {
+ DEBUG(dbgs() << "Starting import for Module "
+ << DestModule.getModuleIdentifier() << "\n");
+ unsigned ImportedCount = 0;
+
+ /// First step is collecting the called external functions.
+ StringSet<> CalledFunctions;
+ SmallVector<StringRef, 64> Worklist;
+ for (auto &F : DestModule) {
+ if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
+ continue;
+ findExternalCalls(F, CalledFunctions, Worklist);
}
- return Changed;
+ if (Worklist.empty())
+ return false;
+
+ /// Second step: for every call to an external function, try to import it.
+
+ // Linker that will be used for importing function
+ Linker TheLinker(DestModule, DiagnosticHandler);
+
+ ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions,
+ TheLinker, Index, ModuleLoader);
+
+ DEBUG(errs() << "Imported " << ImportedCount << " functions for Module "
+ << DestModule.getModuleIdentifier() << "\n");
+ return ImportedCount;
}
/// Summary file to use for function importing when using -function-import from
/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {
+ /// Optional function summary index to use for importing, otherwise
+ /// the summary-file option must be specified.
+ FunctionInfoIndex *Index;
public:
/// Pass identification, replacement for typeid
static char ID;
- explicit FunctionImportPass() : ModulePass(ID) {}
+ /// Specify pass name for debug output
+ const char *getPassName() const override {
+ return "Function Importing";
+ }
+
+ explicit FunctionImportPass(FunctionInfoIndex *Index = nullptr)
+ : ModulePass(ID), Index(Index) {}
bool runOnModule(Module &M) override {
- if (SummaryFile.empty()) {
- report_fatal_error("error: -function-import requires -summary-file\n");
- }
- std::string Error;
- std::unique_ptr<FunctionInfoIndex> Index =
- getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
- if (!Index) {
- errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n";
- return false;
+ if (SummaryFile.empty() && !Index)
+ report_fatal_error("error: -function-import requires -summary-file or "
+ "file from frontend\n");
+ std::unique_ptr<FunctionInfoIndex> IndexPtr;
+ if (!SummaryFile.empty()) {
+ if (Index)
+ report_fatal_error("error: -summary-file and index from frontend\n");
+ std::string Error;
+ IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
+ if (!IndexPtr) {
+ errs() << "Error loading file '" << SummaryFile << "': " << Error
+ << "\n";
+ return false;
+ }
+ Index = IndexPtr.get();
}
// Perform the import now.
- FunctionImporter Importer(M.getContext(), *Index, diagnosticHandler);
+ auto ModuleLoader = [&M](StringRef Identifier) {
+ return loadFile(Identifier, M.getContext());
+ };
+ FunctionImporter Importer(*Index, diagnosticHandler, ModuleLoader);
return Importer.importFunctions(M);
return false;
"Summary Based Function Import", false, false)
namespace llvm {
-Pass *createFunctionImportPass() { return new FunctionImportPass(); }
+Pass *createFunctionImportPass(FunctionInfoIndex *Index = nullptr) {
+ return new FunctionImportPass(Index);
+}
}