[ThinLTO] Remove stale comment (NFC)
[oota-llvm.git] / lib / Transforms / IPO / FunctionImport.cpp
index 725796790ea7997f9b720853b0f65cc11bb4e185..345b2f540adfc4658226ee158bfafbb25e741d37 100644 (file)
@@ -28,6 +28,11 @@ using namespace llvm;
 
 #define DEBUG_TYPE "function-import"
 
+/// Limit on instruction count of imported functions.
+static cl::opt<unsigned> ImportInstrLimit(
+    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
+    cl::desc("Only import functions with less than N instructions"));
+
 // Load lazily a module from \p FileName in \p Context.
 static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                         LLVMContext &Context) {
@@ -53,6 +58,29 @@ Module &FunctionImporter::getOrLoadModule(StringRef FileName) {
   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.
+static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
+                              SmallVector<StringRef, 64> &Worklist) {
+  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.
+        if (CalledFunction && CalledFunction->hasName() &&
+            CalledFunction->isDeclaration() &&
+            !CalledFunctions.count(CalledFunction->getName())) {
+          CalledFunctions.insert(CalledFunction->getName());
+          Worklist.push_back(CalledFunction->getName());
+        }
+      }
+    }
+  }
+}
+
 // Automatically import functions in Module \p M based on the summaries index.
 //
 // The current implementation imports every called functions that exists in the
@@ -62,23 +90,13 @@ bool FunctionImporter::importFunctions(Module &M) {
 
   bool Changed = false;
 
-  /// First step is collecting the called functions and the one defined in this
-  /// module.
+  /// 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;
-    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();
-          if (CalledFunction && CalledFunction->hasName() &&
-              CalledFunction->isDeclaration())
-            CalledFunctions.insert(CalledFunction->getName());
-        }
-      }
-    }
+    findExternalCalls(F, CalledFunctions, Worklist);
   }
 
   /// Second step: for every call to an external function, try to import it.
@@ -86,12 +104,6 @@ bool FunctionImporter::importFunctions(Module &M) {
   // Linker that will be used for importing function
   Linker L(&M, DiagnosticHandler);
 
-  /// Insert initial called function set in a worklist, so that we can add
-  /// transively called functions when importing.
-  SmallVector<StringRef, 64> Worklist;
-  for (auto &CalledFunction : CalledFunctions)
-    Worklist.push_back(CalledFunction.first());
-
   while (!Worklist.empty()) {
     auto CalledFunctionName = Worklist.pop_back_val();
     DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");
@@ -117,9 +129,12 @@ bool FunctionImporter::importFunctions(Module &M) {
       llvm_unreachable("Missing summary");
     }
 
-    //
-    // No profitability notion right now, just import all the time...
-    //
+    if (Summary->instCount() > ImportInstrLimit) {
+      dbgs() << "Skip import of " << CalledFunctionName << " with "
+             << Summary->instCount() << " instructions (limit "
+             << ImportInstrLimit << ")\n";
+      continue;
+    }
 
     // Get the module path from the summary.
     auto FileName = Summary->modulePath();
@@ -131,10 +146,24 @@ bool FunctionImporter::importFunctions(Module &M) {
 
     // The function that we will import!
     GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
+    StringRef ImportFunctionName = CalledFunctionName;
+    if (!SGV) {
+      // Might be local in source Module, promoted/renamed in dest Module M.
+      std::pair<StringRef, StringRef> Split =
+          CalledFunctionName.split(".llvm.");
+      SGV = Module.getNamedValue(Split.first);
+#ifndef NDEBUG
+      // Assert that Split.second is module id
+      uint64_t ModuleId;
+      assert(!Split.second.getAsInteger(10, ModuleId));
+      assert(ModuleId == Index.getModuleId(FileName));
+#endif
+    }
     Function *F = dyn_cast<Function>(SGV);
     if (!F && isa<GlobalAlias>(SGV)) {
       auto *SGA = dyn_cast<GlobalAlias>(SGV);
       F = dyn_cast<Function>(SGA->getBaseObject());
+      ImportFunctionName = F->getName();
     }
     if (!F) {
       errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
@@ -142,11 +171,12 @@ bool FunctionImporter::importFunctions(Module &M) {
       llvm_unreachable("Can't load function in Module");
     }
 
-    // We cannot import weak_any functions without possibly affecting the
-    // order they are seen and selected by the linker, changing program
+    // We cannot import weak_any functions/aliases without possibly affecting
+    // the order they are seen and selected by the linker, changing program
     // semantics.
-    if (F->hasWeakAnyLinkage()) {
-      DEBUG(dbgs() << "Ignoring import request for weak-any function "
+    if (SGV->hasWeakAnyLinkage()) {
+      DEBUG(dbgs() << "Ignoring import request for weak-any "
+                   << (isa<Function>(SGV) ? "function " : "alias ")
                    << CalledFunctionName << " from " << FileName << "\n");
       continue;
     }
@@ -155,8 +185,12 @@ bool FunctionImporter::importFunctions(Module &M) {
     if (L.linkInModule(&Module, Linker::Flags::None, &Index, F))
       report_fatal_error("Function Import: link error");
 
-    // TODO: Process the newly imported function and add callees to the
-    // worklist.
+    // Process the newly imported function and add callees to the worklist.
+    GlobalValue *NewGV = M.getNamedValue(ImportFunctionName);
+    assert(NewGV);
+    Function *NewF = dyn_cast<Function>(NewGV);
+    assert(NewF);
+    findExternalCalls(*NewF, CalledFunctions, Worklist);
 
     Changed = true;
   }