LLVM 19.0.0git
Classes | Namespaces | Macros | Functions | Variables
FunctionImport.cpp File Reference
#include "llvm/Transforms/IPO/FunctionImport.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/IRMover.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <cassert>
#include <memory>
#include <set>
#include <string>
#include <system_error>
#include <tuple>
#include <utility>

Go to the source code of this file.

Classes

class  GlobalsImporter
 Import globals referenced by a function or other globals that are being imported, if importing such global is possible. More...
 
class  ModuleImportsManager
 Determine the list of imports and exports for each module. More...
 
class  WorkloadImportsManager
 A ModuleImportsManager that operates based on a workload definition (see -thinlto-workload-def). More...
 

Namespaces

namespace  llvm
 This is an optimization pass for GlobalISel generic memory operations.
 

Macros

#define DEBUG_TYPE   "function-import"
 

Functions

 STATISTIC (NumImportedFunctionsThinLink, "Number of functions thin link decided to import")
 
 STATISTIC (NumImportedHotFunctionsThinLink, "Number of hot functions thin link decided to import")
 
 STATISTIC (NumImportedCriticalFunctionsThinLink, "Number of critical functions thin link decided to import")
 
 STATISTIC (NumImportedGlobalVarsThinLink, "Number of global variables thin link decided to import")
 
 STATISTIC (NumImportedFunctions, "Number of functions imported in backend")
 
 STATISTIC (NumImportedGlobalVars, "Number of global variables imported in backend")
 
 STATISTIC (NumImportedModules, "Number of modules imported from")
 
 STATISTIC (NumDeadSymbols, "Number of dead stripped symbols in index")
 
 STATISTIC (NumLiveSymbols, "Number of live symbols in index")
 
static std::unique_ptr< ModuleloadFile (const std::string &FileName, LLVMContext &Context)
 
static auto qualifyCalleeCandidates (const ModuleSummaryIndex &Index, ArrayRef< std::unique_ptr< GlobalValueSummary > > CalleeSummaryList, StringRef CallerModulePath)
 Given a list of possible callee implementation for a call site, qualify the legality of importing each.
 
static const GlobalValueSummaryselectCallee (const ModuleSummaryIndex &Index, ArrayRef< std::unique_ptr< GlobalValueSummary > > CalleeSummaryList, unsigned Threshold, StringRef CallerModulePath, FunctionImporter::ImportFailureReason &Reason)
 Given a list of possible callee implementation for a call site, select one that fits the Threshold.
 
static const chargetFailureName (FunctionImporter::ImportFailureReason Reason)
 
static void computeImportForFunction (const FunctionSummary &Summary, const ModuleSummaryIndex &Index, const unsigned Threshold, const GVSummaryMapTy &DefinedGVSummaries, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, SmallVectorImpl< EdgeInfo > &Worklist, GlobalsImporter &GVImporter, FunctionImporter::ImportMapTy &ImportList, DenseMap< StringRef, FunctionImporter::ExportSetTy > *ExportLists, FunctionImporter::ImportThresholdsTy &ImportThresholds)
 Compute the list of functions to import for a given caller.
 
static bool isGlobalVarSummary (const ModuleSummaryIndex &Index, ValueInfo VI)
 
static bool isGlobalVarSummary (const ModuleSummaryIndex &Index, GlobalValue::GUID G)
 
template<class T >
static unsigned numGlobalVarSummaries (const ModuleSummaryIndex &Index, T &Cont)
 
static bool checkVariableImport (const ModuleSummaryIndex &Index, DenseMap< StringRef, FunctionImporter::ImportMapTy > &ImportLists, DenseMap< StringRef, FunctionImporter::ExportSetTy > &ExportLists)
 
static void dumpImportListForModule (const ModuleSummaryIndex &Index, StringRef ModulePath, FunctionImporter::ImportMapTy &ImportList)
 
static void ComputeCrossModuleImportForModuleForTest (StringRef ModulePath, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList)
 Compute all the imports for the given module using the Index.
 
static void ComputeCrossModuleImportForModuleFromIndexForTest (StringRef ModulePath, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList)
 Mark all external summaries in Index for import into the given module.
 
void updateValueInfoForIndirectCalls (ModuleSummaryIndex &Index, FunctionSummary *FS)
 
static FunctionreplaceAliasWithAliasee (Module *SrcModule, GlobalAlias *GA)
 Make alias a clone of its aliasee.
 
static void internalizeGVsAfterImport (Module &M)
 
static bool doImportingForModuleForTest (Module &M, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
 

Variables

static cl::opt< unsignedImportInstrLimit ("import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), cl::desc("Only import functions with less than N instructions"))
 Limit on instruction count of imported functions.
 
static cl::opt< int > 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< boolForceImportAll ("force-import-all", cl::init(false), cl::Hidden, cl::desc("Import functions with noinline attribute"))
 
static cl::opt< float > 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"))
 
static cl::opt< float > ImportHotInstrFactor ("import-hot-evolution-factor", cl::init(1.0), cl::Hidden, cl::value_desc("x"), cl::desc("As we import functions called from hot callsite, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions"))
 
static cl::opt< float > ImportHotMultiplier ("import-hot-multiplier", cl::init(10.0), cl::Hidden, cl::value_desc("x"), cl::desc("Multiply the `import-instr-limit` threshold for hot callsites"))
 
static cl::opt< float > ImportCriticalMultiplier ("import-critical-multiplier", cl::init(100.0), cl::Hidden, cl::value_desc("x"), cl::desc("Multiply the `import-instr-limit` threshold for critical callsites"))
 
static cl::opt< float > ImportColdMultiplier ("import-cold-multiplier", cl::init(0), cl::Hidden, cl::value_desc("N"), cl::desc("Multiply the `import-instr-limit` threshold for cold callsites"))
 
static cl::opt< boolPrintImports ("print-imports", cl::init(false), cl::Hidden, cl::desc("Print imported functions"))
 
static cl::opt< boolPrintImportFailures ("print-import-failures", cl::init(false), cl::Hidden, cl::desc("Print information for functions rejected for importing"))
 
static cl::opt< boolComputeDead ("compute-dead", cl::init(true), cl::Hidden, cl::desc("Compute dead symbols"))
 
static cl::opt< boolEnableImportMetadata ("enable-import-metadata", cl::init(false), cl::Hidden, cl::desc("Enable import metadata like 'thinlto_src_module' and " "'thinlto_src_file'"))
 
static cl::opt< std::string > SummaryFile ("summary-file", cl::desc("The summary file to use for function importing."))
 Summary file to use for function importing when using -function-import from the command line.
 
static cl::opt< boolImportAllIndex ("import-all-index", cl::desc("Import all external functions in index."))
 Used when testing importing from distributed indexes via opt.
 
static cl::opt< std::string > WorkloadDefinitions ("thinlto-workload-def", cl::desc("Pass a workload definition. This is a file containing a JSON " "dictionary. The keys are root functions, the values are lists of " "functions to import in the module defining the root. It is " "assumed -funique-internal-linkage-names was used, to ensure " "local linkage functions have unique names. For example: \n" "{\n" " \"rootFunction_1\": [\"function_to_import_1\", " "\"function_to_import_2\"], \n" " \"rootFunction_2\": [\"function_to_import_3\", " "\"function_to_import_4\"] \n" "}"), cl::Hidden)
 Pass a workload description file - an example of workload would be the functions executed to satisfy a RPC request.
 

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "function-import"

Definition at line 57 of file FunctionImport.cpp.

Function Documentation

◆ checkVariableImport()

static bool checkVariableImport ( const ModuleSummaryIndex Index,
DenseMap< StringRef, FunctionImporter::ImportMapTy > &  ImportLists,
DenseMap< StringRef, FunctionImporter::ExportSetTy > &  ExportLists 
)
static

◆ ComputeCrossModuleImportForModuleForTest()

static void ComputeCrossModuleImportForModuleForTest ( StringRef  ModulePath,
function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)>  isPrevailing,
const ModuleSummaryIndex Index,
FunctionImporter::ImportMapTy ImportList 
)
static

Compute all the imports for the given module using the Index.

isPrevailing is a callback that will be called with a global value's GUID and summary and should return whether the module corresponding to the summary contains the linker-prevailing copy of that value.

ImportList will be populated with a map that can be passed to FunctionImporter::importFunctions() above (see description there).

Definition at line 1109 of file FunctionImport.cpp.

References ModuleImportsManager::create(), llvm::dbgs(), dumpImportListForModule(), and LLVM_DEBUG.

Referenced by doImportingForModuleForTest().

◆ ComputeCrossModuleImportForModuleFromIndexForTest()

static void ComputeCrossModuleImportForModuleFromIndexForTest ( StringRef  ModulePath,
const ModuleSummaryIndex Index,
FunctionImporter::ImportMapTy ImportList 
)
static

Mark all external summaries in Index for import into the given module.

Used for testing the case of distributed builds using a distributed index.

ImportList will be populated with a map that can be passed to FunctionImporter::importFunctions() above (see description there).

Definition at line 1135 of file FunctionImport.cpp.

References assert(), dumpImportListForModule(), and llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::insert().

Referenced by doImportingForModuleForTest().

◆ computeImportForFunction()

static void computeImportForFunction ( const FunctionSummary Summary,
const ModuleSummaryIndex Index,
const unsigned  Threshold,
const GVSummaryMapTy DefinedGVSummaries,
function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)>  isPrevailing,
SmallVectorImpl< EdgeInfo > &  Worklist,
GlobalsImporter GVImporter,
FunctionImporter::ImportMapTy ImportList,
DenseMap< StringRef, FunctionImporter::ExportSetTy > *  ExportLists,
FunctionImporter::ImportThresholdsTy ImportThresholds 
)
static

◆ doImportingForModuleForTest()

static bool doImportingForModuleForTest ( Module M,
function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)>  isPrevailing 
)
static

◆ dumpImportListForModule()

static void dumpImportListForModule ( const ModuleSummaryIndex Index,
StringRef  ModulePath,
FunctionImporter::ImportMapTy ImportList 
)
static

◆ getFailureName()

static const char * getFailureName ( FunctionImporter::ImportFailureReason  Reason)
static

◆ internalizeGVsAfterImport()

static void internalizeGVsAfterImport ( Module M)
static

◆ isGlobalVarSummary() [1/2]

static bool isGlobalVarSummary ( const ModuleSummaryIndex Index,
GlobalValue::GUID  G 
)
static

Definition at line 934 of file FunctionImport.cpp.

References G, and isGlobalVarSummary().

◆ isGlobalVarSummary() [2/2]

static bool isGlobalVarSummary ( const ModuleSummaryIndex Index,
ValueInfo  VI 
)
static

◆ loadFile()

static std::unique_ptr< Module > loadFile ( const std::string &  FileName,
LLVMContext Context 
)
static

◆ numGlobalVarSummaries()

template<class T >
static unsigned numGlobalVarSummaries ( const ModuleSummaryIndex Index,
T Cont 
)
static

Definition at line 942 of file FunctionImport.cpp.

References isGlobalVarSummary().

Referenced by llvm::ComputeCrossModuleImport(), and dumpImportListForModule().

◆ qualifyCalleeCandidates()

static auto qualifyCalleeCandidates ( const ModuleSummaryIndex Index,
ArrayRef< std::unique_ptr< GlobalValueSummary > >  CalleeSummaryList,
StringRef  CallerModulePath 
)
static

Given a list of possible callee implementation for a call site, qualify the legality of importing each.

The return is a range of pairs. Each pair corresponds to a candidate. The first value is the ImportFailureReason for that candidate, the second is the candidate.

Definition at line 192 of file FunctionImport.cpp.

References if(), llvm::GlobalValue::isInterposableLinkage(), llvm::GlobalValue::isLocalLinkage(), and llvm::map_range().

Referenced by selectCallee().

◆ replaceAliasWithAliasee()

static Function * replaceAliasWithAliasee ( Module SrcModule,
GlobalAlias GA 
)
static

◆ selectCallee()

static const GlobalValueSummary * selectCallee ( const ModuleSummaryIndex Index,
ArrayRef< std::unique_ptr< GlobalValueSummary > >  CalleeSummaryList,
unsigned  Threshold,
StringRef  CallerModulePath,
FunctionImporter::ImportFailureReason Reason 
)
static

Given a list of possible callee implementation for a call site, select one that fits the Threshold.

If none are found, the Reason will give the last reason for the failure (last, in the order of CalleeSummaryList entries).

FIXME: select "best" instead of first that fits. But what is "best"?

  • The smallest: more likely to be inlined.
  • The one with the least outgoing edges (already well optimized).
  • One from a module already being imported from in order to reduce the number of source modules parsed/linked.
  • One that has PGO data attached.
  • [insert you fancy metric here]

Definition at line 259 of file FunctionImport.cpp.

References ForceImportAll, and qualifyCalleeCandidates().

Referenced by computeImportForFunction().

◆ STATISTIC() [1/9]

STATISTIC ( NumDeadSymbols  ,
"Number of dead stripped symbols in index"   
)

◆ STATISTIC() [2/9]

STATISTIC ( NumImportedCriticalFunctionsThinLink  ,
"Number of critical functions thin link decided to import"   
)

◆ STATISTIC() [3/9]

STATISTIC ( NumImportedFunctions  ,
"Number of functions imported in backend"   
)

◆ STATISTIC() [4/9]

STATISTIC ( NumImportedFunctionsThinLink  ,
"Number of functions thin link decided to import"   
)

◆ STATISTIC() [5/9]

STATISTIC ( NumImportedGlobalVars  ,
"Number of global variables imported in backend"   
)

◆ STATISTIC() [6/9]

STATISTIC ( NumImportedGlobalVarsThinLink  ,
"Number of global variables thin link decided to import"   
)

◆ STATISTIC() [7/9]

STATISTIC ( NumImportedHotFunctionsThinLink  ,
"Number of hot functions thin link decided to import"   
)

◆ STATISTIC() [8/9]

STATISTIC ( NumImportedModules  ,
"Number of modules imported from"   
)

◆ STATISTIC() [9/9]

STATISTIC ( NumLiveSymbols  ,
"Number of live symbols in index"   
)

◆ updateValueInfoForIndirectCalls()

void updateValueInfoForIndirectCalls ( ModuleSummaryIndex Index,
FunctionSummary FS 
)

Variable Documentation

◆ ComputeDead

cl::opt< bool > ComputeDead("compute-dead", cl::init(true), cl::Hidden, cl::desc("Compute dead symbols")) ( "compute-dead"  ,
cl::init(true ,
cl::Hidden  ,
cl::desc("Compute dead symbols")   
)
static

◆ EnableImportMetadata

cl::opt< bool > EnableImportMetadata("enable-import-metadata", cl::init(false), cl::Hidden, cl::desc("Enable import metadata like 'thinlto_src_module' and " "'thinlto_src_file'")) ( "enable-import-metadata"  ,
cl::init(false)  ,
cl::Hidden  ,
cl::desc("Enable import metadata like 'thinlto_src_module' and " "'thinlto_src_file'")   
)
static

◆ ForceImportAll

cl::opt< bool > ForceImportAll("force-import-all", cl::init(false), cl::Hidden, cl::desc("Import functions with noinline attribute")) ( "force-import-all"  ,
cl::init(false)  ,
cl::Hidden  ,
cl::desc("Import functions with noinline attribute")   
)
static

◆ ImportAllIndex

cl::opt< bool > ImportAllIndex("import-all-index", cl::desc("Import all external functions in index.")) ( "import-all-index"  ,
cl::desc("Import all external functions in index.")   
)
static

Used when testing importing from distributed indexes via opt.

Referenced by doImportingForModuleForTest().

◆ ImportColdMultiplier

cl::opt< float > ImportColdMultiplier("import-cold-multiplier", cl::init(0), cl::Hidden, cl::value_desc("N"), cl::desc("Multiply the `import-instr-limit` threshold for cold callsites")) ( "import-cold-multiplier"  ,
cl::init(0)  ,
cl::Hidden  ,
cl::value_desc("N")  ,
cl::desc("Multiply the `import-instr-limit` threshold for cold callsites")   
)
static

◆ ImportCriticalMultiplier

cl::opt< float > ImportCriticalMultiplier("import-critical-multiplier", cl::init(100.0), cl::Hidden, cl::value_desc("x"), cl::desc( "Multiply the `import-instr-limit` threshold for critical callsites")) ( "import-critical-multiplier"  ,
cl::init(100.0)  ,
cl::Hidden  ,
cl::value_desc("x")  ,
cl::desc( "Multiply the `import-instr-limit` threshold for critical callsites")   
)
static

◆ ImportCutoff

cl::opt< int > ImportCutoff("import-cutoff", cl::init(-1), cl::Hidden, cl::value_desc("N"), cl::desc("Only import first N functions if N>=0 (default -1)")) ( "import-cutoff"  ,
cl::init(-1)  ,
cl::Hidden  ,
cl::value_desc("N")  ,
cl::desc("Only import first N functions if N>=0 (default -1)")   
)
static

◆ ImportHotInstrFactor

cl::opt< float > ImportHotInstrFactor("import-hot-evolution-factor", cl::init(1.0), cl::Hidden, cl::value_desc("x"), cl::desc("As we import functions called from hot callsite, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions")) ( "import-hot-evolution-factor"  ,
cl::init(1.0)  ,
cl::Hidden  ,
cl::value_desc("x")  ,
cl::desc("As we import functions called from hot callsite, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions")   
)
static

◆ ImportHotMultiplier

cl::opt< float > ImportHotMultiplier("import-hot-multiplier", cl::init(10.0), cl::Hidden, cl::value_desc("x"), cl::desc("Multiply the `import-instr-limit` threshold for hot callsites")) ( "import-hot-multiplier"  ,
cl::init(10.0)  ,
cl::Hidden  ,
cl::value_desc("x")  ,
cl::desc("Multiply the `import-instr-limit` threshold for hot callsites")   
)
static

◆ ImportInstrFactor

cl::opt< float > 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")) ( "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")   
)
static

◆ ImportInstrLimit

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")) ( "import-instr-limit"  ,
cl::init(100)  ,
cl::Hidden  ,
cl::value_desc("N")  ,
cl::desc("Only import functions with less than N instructions")   
)
static

Limit on instruction count of imported functions.

Referenced by ModuleImportsManager::computeImportForModule().

◆ PrintImportFailures

cl::opt< bool > PrintImportFailures("print-import-failures", cl::init(false), cl::Hidden, cl::desc("Print information for functions rejected for importing")) ( "print-import-failures"  ,
cl::init(false)  ,
cl::Hidden  ,
cl::desc("Print information for functions rejected for importing")   
)
static

◆ PrintImports

cl::opt< bool > PrintImports("print-imports", cl::init(false), cl::Hidden, cl::desc("Print imported functions")) ( "print-imports"  ,
cl::init(false)  ,
cl::Hidden  ,
cl::desc("Print imported functions")   
)
static

◆ SummaryFile

cl::opt< std::string > SummaryFile("summary-file", cl::desc("The summary file to use for function importing.")) ( "summary-file"  ,
cl::desc("The summary file to use for function importing.")   
)
static

Summary file to use for function importing when using -function-import from the command line.

Referenced by doImportingForModuleForTest().

◆ WorkloadDefinitions

cl::opt< std::string > WorkloadDefinitions("thinlto-workload-def", cl::desc("Pass a workload definition. This is a file containing a JSON " "dictionary. The keys are root functions, the values are lists of " "functions to import in the module defining the root. It is " "assumed -funique-internal-linkage-names was used, to ensure " "local linkage functions have unique names. For example: \n" "{\n" " \"rootFunction_1\": [\"function_to_import_1\", " "\"function_to_import_2\"], \n" " \"rootFunction_2\": [\"function_to_import_3\", " "\"function_to_import_4\"] \n" "}"), cl::Hidden) ( "thinlto-workload-def"  ,
cl::desc("Pass a workload definition. This is a file containing a JSON " "dictionary. The keys are root functions, the values are lists of " "functions to import in the module defining the root. It is " "assumed -funique-internal-linkage-names was used, to ensure " "local linkage functions have unique names. For example: \n" "{\n" " \"rootFunction_1\": [\"function_to_import_1\", " "\"function_to_import_2\"], \n" " \"rootFunction_2\": [\"function_to_import_3\", " "\"function_to_import_4\"] \n" "}")  ,
cl::Hidden   
)
static

Pass a workload description file - an example of workload would be the functions executed to satisfy a RPC request.

A workload is defined by a root function and the list of functions that are (frequently) needed to satisfy it. The module that defines the root will have all those functions imported. The file contains a JSON dictionary. The keys are root functions, the values are lists of functions to import in the module defining the root. It is assumed -funique-internal-linkage-names was used, thus ensuring function names are unique even for local linkage ones.

Referenced by ModuleImportsManager::create(), and WorkloadImportsManager::WorkloadImportsManager().