Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -36,6 +36,13 @@ "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), cl::desc("Only import functions with less than N instructions")); +static cl::opt + ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7), + cl::Hidden, cl::value_desc("x"), + cl::desc("As we import functions, multiply the " + "`import-instr-limit` threshold by this factor " + "before processing newly imported functions")); + // Load lazily a module from \p FileName in \p Context. static std::unique_ptr loadFile(const std::string &FileName, LLVMContext &Context) { @@ -94,10 +101,11 @@ /// 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 Module &DestModule, Function &F, - const FunctionInfoIndex &Index, - StringSet<> &CalledFunctions, - SmallVector &Worklist) { +static void +findExternalCalls(const Module &DestModule, Function &F, + const FunctionInfoIndex &Index, StringSet<> &CalledFunctions, + unsigned Threshold, + SmallVectorImpl> &Worklist) { // We need to suffix internal function calls imported from other modules, // prepare the suffix ahead of time. std::string Suffix; @@ -143,7 +151,7 @@ } } - Worklist.push_back(It.first->getKey()); + Worklist.push_back(std::make_pair(It.first->getKey(), Threshold)); DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Adding callee for : " << ImportedName << " : " << F.getName() << "\n"); @@ -160,15 +168,18 @@ // // \p ModuleToFunctionsToImportMap is filled with the set of Function to import // per Module. -static void GetImportList(Module &DestModule, - SmallVector &Worklist, - StringSet<> &CalledFunctions, - std::map> - &ModuleToFunctionsToImportMap, - const FunctionInfoIndex &Index, - ModuleLazyLoaderCache &ModuleLoaderCache) { +static void +GetImportList(Module &DestModule, + SmallVectorImpl> &Worklist, + StringSet<> &CalledFunctions, + std::map> & + ModuleToFunctionsToImportMap, + const FunctionInfoIndex &Index, + ModuleLazyLoaderCache &ModuleLoaderCache) { while (!Worklist.empty()) { - auto CalledFunctionName = Worklist.pop_back_val(); + StringRef CalledFunctionName; + unsigned Threshold; + std::tie(CalledFunctionName, Threshold) = Worklist.pop_back_val(); DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Process import for " << CalledFunctionName << "\n"); @@ -194,10 +205,10 @@ llvm_unreachable("Missing summary"); } - if (Summary->instCount() > ImportInstrLimit) { + if (Summary->instCount() > Threshold) { DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Skip import of " << CalledFunctionName << " with " << Summary->instCount() - << " instructions (limit " << ImportInstrLimit << ")\n"); + << " instructions (limit " << Threshold << ")\n"); continue; } @@ -253,8 +264,11 @@ Entry.insert(F); // Process the newly imported functions and add callees to the worklist. + // Adjust the threshold + Threshold = Threshold * ImportInstrFactor; F->materialize(); - findExternalCalls(DestModule, *F, Index, CalledFunctions, Worklist); + findExternalCalls(DestModule, *F, Index, CalledFunctions, Threshold, + Worklist); } } @@ -268,13 +282,15 @@ << DestModule.getModuleIdentifier() << "\n"); unsigned ImportedCount = 0; - /// First step is collecting the called external functions. + // First step is collecting the called external functions. + // We keep the function name as long as the import threshold for its callees. StringSet<> CalledFunctions; - SmallVector Worklist; + SmallVector, 64> Worklist; for (auto &F : DestModule) { if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone)) continue; - findExternalCalls(DestModule, F, Index, CalledFunctions, Worklist); + findExternalCalls(DestModule, F, Index, CalledFunctions, ImportInstrLimit, + Worklist); } if (Worklist.empty()) return false; Index: test/Transforms/FunctionImport/adjustable_threshold.ll =================================================================== --- /dev/null +++ test/Transforms/FunctionImport/adjustable_threshold.ll @@ -0,0 +1,23 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: llvm-as -function-summary %s -o %t.bc +; RUN: llvm-as -function-summary %p/Inputs/funcimport.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; Test import with default progressive instruction factor +; RUN: opt -function-import -summary-file %t3.thinlto.bc %s -import-instr-limit=10 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM-DEFAULT +; INSTLIM-DEFAULT: call void @globalfunc2() + +; Test import with a reduced progressive instruction factor +; RUN: opt -function-import -summary-file %t3.thinlto.bc %s -import-instr-limit=10 -import-instr-evolution-factor=0.5 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM-PROGRESSIVE +; INSTLIM-PROGRESSIVE-NOT: call void @globalfunc2() + + + +declare void @globalfunc1() + +define void @entry() { +entry: + call void @globalfunc1() + ret void +} +