X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FFunctionImport.cpp;h=345b2f540adfc4658226ee158bfafbb25e741d37;hb=2b9196851ccf22799f23c75377672a93a5c02665;hp=725796790ea7997f9b720853b0f65cc11bb4e185;hpb=a7649e87bb21bc913ae78a399a35354866b8dd72;p=oota-llvm.git diff --git a/lib/Transforms/IPO/FunctionImport.cpp b/lib/Transforms/IPO/FunctionImport.cpp index 725796790ea..345b2f540ad 100644 --- a/lib/Transforms/IPO/FunctionImport.cpp +++ b/lib/Transforms/IPO/FunctionImport.cpp @@ -28,6 +28,11 @@ using namespace llvm; #define DEBUG_TYPE "function-import" +/// Limit on instruction count of imported functions. +static cl::opt 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 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 &Worklist) { + for (auto &BB : F) { + for (auto &I : BB) { + if (isa(I)) { + DEBUG(dbgs() << "Found a call: '" << I << "'\n"); + auto CalledFunction = cast(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 Worklist; for (auto &F : M) { if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone)) continue; - for (auto &BB : F) { - for (auto &I : BB) { - if (isa(I)) { - DEBUG(dbgs() << "Found a call: '" << I << "'\n"); - auto CalledFunction = cast(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 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 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(SGV); if (!F && isa(SGV)) { auto *SGA = dyn_cast(SGV); F = dyn_cast(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(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(NewGV); + assert(NewF); + findExternalCalls(*NewF, CalledFunctions, Worklist); Changed = true; }