Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -71,6 +71,10 @@ "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 ImportCutoff( + "import-cutoff", cl::init(-1), cl::Hidden, cl::value_desc("N"), + cl::desc("Only import first N functions if N>=0 (default -1)")); + static cl::opt ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7), cl::Hidden, cl::value_desc("x"), @@ -276,11 +280,18 @@ StringMap *ExportLists = nullptr) { computeImportForReferencedGlobals(Summary, DefinedGVSummaries, ImportList, ExportLists); + static int ImportCount = 0; for (auto &Edge : Summary.calls()) { ValueInfo VI = Edge.first; DEBUG(dbgs() << " edge -> " << VI.getGUID() << " Threshold:" << Threshold << "\n"); + if (ImportCutoff >= 0 && ImportCount >= ImportCutoff) { + DEBUG(dbgs() << "ignored! import-cutoff value of " << ImportCutoff + << " reached.\n"); + continue; + } + VI = updateValueInfoForIndirectCalls(Index, VI); if (!VI) continue; @@ -343,6 +354,8 @@ // Mark this function as imported in this module, with the current Threshold ProcessedThreshold = AdjThreshold; + ImportCount++; + // Make exports in the source module. if (ExportLists) { auto &ExportList = (*ExportLists)[ExportModulePath]; Index: test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll =================================================================== --- /dev/null +++ test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll @@ -0,0 +1,9 @@ +define void @foo() { +entry: + ret void +} + +define void @bar() { +entry: + ret void +} Index: test/Transforms/FunctionImport/funcimport_cutoff.ll =================================================================== --- /dev/null +++ test/Transforms/FunctionImport/funcimport_cutoff.ll @@ -0,0 +1,49 @@ +; Test to ensure that thin linking with -import-cutoff stops importing when +; expected. + +; "-stats" and "-debug-only" require +Asserts. +; REQUIRES: asserts + +; RUN: opt -module-summary %s -o %t.bc +; RUN: opt -module-summary %p/Inputs/funcimport_cutoff.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; First do with default options, which should import both foo and bar +; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT + +; Next try to restrict to 1 import. This should import just foo. +; RUN: opt -import-cutoff=1 -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT1 + +; Next try to restrict to 0 imports. This should not import. +; RUN: opt -import-cutoff=0 -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT + +define i32 @main() { +entry: + call void @foo() + call void @bar() + ret i32 0 +} + +declare void @foo() +declare void @bar() + +; Check -print-imports output +; IMPORT: Import foo +; IMPORT: Import bar +; IMPORT1: Import foo +; IMPORT1-NOT: Import bar +; NOIMPORT-NOT: Import foo +; NOIMPORT-NOT: Import bar + +; Check -S output +; IMPORT-DAG: define available_externally void @foo() +; IMPORT-DAG: define available_externally void @bar() +; NOIMPORT-DAG: declare void @foo() +; NOIMPORT-DAG: declare void @bar() +; IMPORT1-DAG: define available_externally void @foo() +; IMPORT1-DAG: declare void @bar() + +; Check -stats output +; IMPORT: 2 function-import - Number of functions imported +; IMPORT1: 1 function-import - Number of functions imported +; NOIMPORT-NOT: function-import - Number of functions imported