Skip to content

Commit

Permalink
ThinLTO: use the callgraph from the combined index to drive the Funct…
Browse files Browse the repository at this point in the history
…ionImporter

Summary:
Now that the summary contains the full reference/call graph, we can
replace the existing function importer that loads and inspect the IR
to iteratively walk the call graph by a traversal based purely on the
summary information. Decouple the actual importing decision from any
IR manipulation.

Reviewers: tejohnson

Subscribers: llvm-commits, joker.eph

Differential Revision: http://reviews.llvm.org/D18343

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 264503
  • Loading branch information
joker-eph committed Mar 26, 2016
1 parent 4022168 commit 01e3213
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 270 deletions.
45 changes: 38 additions & 7 deletions llvm/include/llvm/Transforms/IPO/FunctionImport.h
Expand Up @@ -11,7 +11,10 @@
#define LLVM_FUNCTIONIMPORT_H

#include "llvm/ADT/StringMap.h"

#include <functional>
#include <map>
#include <unordered_set>

namespace llvm {
class LLVMContext;
Expand All @@ -21,23 +24,51 @@ class ModuleSummaryIndex;
/// The function importer is automatically importing function from other modules
/// based on the provided summary informations.
class FunctionImporter {
public:
/// Set of functions to import from a source module. Each entry is a map
/// containing all the functions to import for a source module.
/// The keys is the GUID identifying a function to import, and the value
/// is the threshold applied when deciding to import it.
typedef std::map<uint64_t, unsigned> FunctionsToImportTy;

/// The summaries index used to trigger importing.
const ModuleSummaryIndex &Index;
/// The map contains an entry for every module to import from, the key being
/// the module identifier to pass to the ModuleLoader. The value is the set of
/// functions to import.
typedef StringMap<FunctionsToImportTy> ImportMapTy;

/// Factory function to load a Module for a given identifier
std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader;
/// The set contains an entry for every global value the module exports.
typedef std::unordered_set<uint64_t> ExportSetTy;

public:
/// Create a Function Importer.
FunctionImporter(
const ModuleSummaryIndex &Index,
std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader)
: Index(Index), ModuleLoader(ModuleLoader) {}

/// Import functions in Module \p M based on the summary informations.
bool importFunctions(Module &M);
/// Import functions in Module \p M based on the supplied import list.
bool importFunctions(Module &M, const ImportMapTy &ImportList);

private:
/// The summaries index used to trigger importing.
const ModuleSummaryIndex &Index;

/// Factory function to load a Module for a given identifier
std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader;
};

/// Compute all the imports and exports for every module in the Index.
///
/// \p ImportLists will be populated with an entry for every Module we are
/// importing into. This entry is itself a map that can be passed to
/// FunctionImporter::importFunctions() above (see description there).
///
/// \p ExportLists contains for each Module the set of globals (GUID) that will
/// be imported by another module, or referenced by such a function. I.e. this
/// is the set of globals that need to be promoted/renamed appropriately.
void ComputeCrossModuleImport(
const ModuleSummaryIndex &Index,
StringMap<FunctionImporter::ImportMapTy> &ImportLists,
StringMap<FunctionImporter::ExportSetTy> &ExportLists);
}

#endif // LLVM_FUNCTIONIMPORT_H
34 changes: 26 additions & 8 deletions llvm/lib/LTO/ThinLTOCodeGenerator.cpp
Expand Up @@ -131,12 +131,13 @@ static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index) {
report_fatal_error("renameModuleForThinLTO failed");
}

static void crossImportIntoModule(Module &TheModule,
const ModuleSummaryIndex &Index,
StringMap<MemoryBufferRef> &ModuleMap) {
static void
crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
StringMap<MemoryBufferRef> &ModuleMap,
const FunctionImporter::ImportMapTy &ImportList) {
ModuleLoader Loader(TheModule.getContext(), ModuleMap);
FunctionImporter Importer(Index, Loader);
Importer.importFunctions(TheModule);
Importer.importFunctions(TheModule, ImportList);
}

static void optimizeModule(Module &TheModule, TargetMachine &TM) {
Expand Down Expand Up @@ -185,6 +186,7 @@ std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
static std::unique_ptr<MemoryBuffer>
ProcessThinLTOModule(Module &TheModule, const ModuleSummaryIndex &Index,
StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
const FunctionImporter::ImportMapTy &ImportList,
ThinLTOCodeGenerator::CachingOptions CacheOptions,
StringRef SaveTempsDir, unsigned count) {

Expand All @@ -200,7 +202,7 @@ ProcessThinLTOModule(Module &TheModule, const ModuleSummaryIndex &Index,
// Save temps: after promotion.
saveTempBitcode(TheModule, SaveTempsDir, count, ".2.promoted.bc");

crossImportIntoModule(TheModule, Index, ModuleMap);
crossImportIntoModule(TheModule, Index, ModuleMap, ImportList);

// Save temps: after cross-module import.
saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
Expand Down Expand Up @@ -317,7 +319,15 @@ void ThinLTOCodeGenerator::promote(Module &TheModule,
void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
ModuleSummaryIndex &Index) {
auto ModuleMap = generateModuleMap(Modules);
crossImportIntoModule(TheModule, Index, ModuleMap);

// Generate import/export list
auto ModuleCount = Index.modulePaths().size();
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
ComputeCrossModuleImport(Index, ImportLists, ExportLists);
auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];

crossImportIntoModule(TheModule, Index, ModuleMap, ImportList);
}

/**
Expand Down Expand Up @@ -358,6 +368,13 @@ void ThinLTOCodeGenerator::run() {

// Prepare the module map.
auto ModuleMap = generateModuleMap(Modules);
auto ModuleCount = Modules.size();

// Collect the import/export lists for all modules from the call-graph in the
// combined index.
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
ComputeCrossModuleImport(*Index, ImportLists, ExportLists);

// Parallel optimizer + codegen
{
Expand All @@ -376,9 +393,10 @@ void ThinLTOCodeGenerator::run() {
saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
}

auto &ImportList = ImportLists[TheModule->getModuleIdentifier()];
ProducedBinaries[count] = ProcessThinLTOModule(
*TheModule, *Index, ModuleMap, *TMBuilder.create(), CacheOptions,
SaveTempsDir, count);
*TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
CacheOptions, SaveTempsDir, count);
}, count);
count++;
}
Expand Down

0 comments on commit 01e3213

Please sign in to comment.