[ThinLTO] Enable iterative importing in FunctionImport pass
authorTeresa Johnson <tejohnson@google.com>
Tue, 24 Nov 2015 19:55:04 +0000 (19:55 +0000)
committerTeresa Johnson <tejohnson@google.com>
Tue, 24 Nov 2015 19:55:04 +0000 (19:55 +0000)
Analyze imported function bodies and add any new external calls to
the worklist for importing. Currently no controls on the importing
so this will end up importing everything possible in the call tree
below the importing module. Basic profitability checks coming next.

Update test to check for iteratively inlined functions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254011 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/FunctionImport.cpp
test/Transforms/FunctionImport/funcimport.ll

index c874e4f5da769303d908030dbe8b9b1622786623..bd6eb8391dce515f44122b1773efa3b90dae6ad6 100644 (file)
@@ -131,10 +131,24 @@ bool FunctionImporter::importFunctions(Module &M) {
 
     // The function that we will import!
     GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
 
     // 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());
     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 '"
     }
     if (!F) {
       errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
@@ -156,8 +170,28 @@ bool FunctionImporter::importFunctions(Module &M) {
     if (L.linkInModule(&Module, Linker::Flags::None, &Index, F))
       report_fatal_error("Function Import: link error");
 
     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);
+
+    for (auto &BB : *NewF) {
+      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());
+          }
+        }
+      }
+    }
 
     Changed = true;
   }
 
     Changed = true;
   }
index 43b2fb7919d759ad786982a0cab18e294ad1c858..553d05bfcf3462fb2b1983305fa74c5f0cd5acb9 100644 (file)
@@ -31,9 +31,19 @@ declare void @analias(...) #1
 ; CHECK-DAG: define available_externally i32 @referencestatics(i32 %i)
 declare i32 @referencestatics(...) #1
 
 ; CHECK-DAG: define available_externally i32 @referencestatics(i32 %i)
 declare i32 @referencestatics(...) #1
 
+; The import of referencestatics will expose call to staticfunc that
+; should in turn be imported as a promoted/renamed and hidden function.
+; Ensure that the call is to the properly-renamed function.
+; CHECK-DAG: %call = call i32 @staticfunc.llvm.2()
+; CHECK-DAG: define available_externally hidden i32 @staticfunc.llvm.2()
+
 ; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i)
 declare i32 @referenceglobals(...) #1
 
 ; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i)
 declare i32 @referenceglobals(...) #1
 
+; The import of referenceglobals will expose call to globalfunc1 that
+; should in turn be imported.
+; CHECK-DAG: define available_externally void @globalfunc1()
+
 ; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i)
 declare i32 @referencecommon(...) #1
 
 ; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i)
 declare i32 @referencecommon(...) #1