Add a libLTO API to stop/restart ThinLTO between optimizations and CodeGen

This allows the linker to instruct ThinLTO to perform only the
optimization part or only the codegen part of the process.

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 265113
This commit is contained in:
Mehdi Amini 2016-04-01 06:47:02 +00:00
parent c754367d2e
commit a7205432cb
5 changed files with 83 additions and 5 deletions

View File

@ -44,7 +44,8 @@ typedef bool lto_bool_t;
* @{ * @{
*/ */
#define LTO_API_VERSION 18 #define LTO_API_VERSION 19
/** /**
* \since prior to LTO_API_VERSION=3 * \since prior to LTO_API_VERSION=3
*/ */
@ -717,6 +718,23 @@ extern void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
*/ */
extern void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu); extern void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu);
/**
* Disable CodeGen, only run the stages till codegen and stop. The output will
* be bitcode.
*
* \since LTO_API_VERSION=19
*/
extern void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
lto_bool_t disable);
/**
* Perform CodeGen only: disable all other stages.
*
* \since LTO_API_VERSION=19
*/
extern void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
lto_bool_t codegen_only);
/** /**
* Parse -mllvm style debug options. * Parse -mllvm style debug options.
* *

View File

@ -169,6 +169,13 @@ public:
TMBuilder.CGOptLevel = CGOptLevel; TMBuilder.CGOptLevel = CGOptLevel;
} }
/// Disable CodeGen, only run the stages till codegen and stop. The output
/// will be bitcode.
void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
/// Perform CodeGen only: disable all other stages.
void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
/**@}*/ /**@}*/
/** /**
@ -228,6 +235,14 @@ private:
/// Path to a directory to save the temporary bitcode files. /// Path to a directory to save the temporary bitcode files.
std::string SaveTempsDir; std::string SaveTempsDir;
/// Flag to enable/disable CodeGen. When set to true, the process stops after
/// optimizations and a bitcode is produced.
bool DisableCodeGen;
/// Flag to indicate that only the CodeGen will be performed, no cross-module
/// importing or optimization.
bool CodeGenOnly;
}; };
} }
#endif #endif

View File

@ -188,7 +188,8 @@ ProcessThinLTOModule(Module &TheModule, const ModuleSummaryIndex &Index,
StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM, StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ImportMapTy &ImportList,
ThinLTOCodeGenerator::CachingOptions CacheOptions, ThinLTOCodeGenerator::CachingOptions CacheOptions,
StringRef SaveTempsDir, unsigned count) { bool DisableCodeGen, StringRef SaveTempsDir,
unsigned count) {
// Save temps: after IPO. // Save temps: after IPO.
saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc"); saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc");
@ -212,6 +213,16 @@ ProcessThinLTOModule(Module &TheModule, const ModuleSummaryIndex &Index,
saveTempBitcode(TheModule, SaveTempsDir, count, ".3.opt.bc"); saveTempBitcode(TheModule, SaveTempsDir, count, ".3.opt.bc");
if (DisableCodeGen) {
// Configured to stop before CodeGen, serialize the bitcode and return.
SmallVector<char, 128> OutputBuffer;
{
raw_svector_ostream OS(OutputBuffer);
WriteBitcodeToFile(&TheModule, OS, true, true);
}
return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
}
return codegenModule(TheModule, TM); return codegenModule(TheModule, TM);
} }
@ -348,6 +359,28 @@ std::unique_ptr<MemoryBuffer> ThinLTOCodeGenerator::codegen(Module &TheModule) {
// Main entry point for the ThinLTO processing // Main entry point for the ThinLTO processing
void ThinLTOCodeGenerator::run() { void ThinLTOCodeGenerator::run() {
if (CodeGenOnly) {
// Perform only parallel codegen and return.
ThreadPool Pool;
assert(ProducedBinaries.empty() && "The generator should not be reused");
ProducedBinaries.resize(Modules.size());
int count = 0;
for (auto &ModuleBuffer : Modules) {
Pool.async([&](int count) {
LLVMContext Context;
Context.setDiscardValueNames(LTODiscardValueNames);
// Parse module now
auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
// CodeGen
ProducedBinaries[count] = codegen(*TheModule);
}, count++);
}
return;
}
// Sequential linking phase // Sequential linking phase
auto Index = linkCombinedIndex(); auto Index = linkCombinedIndex();
@ -396,7 +429,7 @@ void ThinLTOCodeGenerator::run() {
auto &ImportList = ImportLists[TheModule->getModuleIdentifier()]; auto &ImportList = ImportLists[TheModule->getModuleIdentifier()];
ProducedBinaries[count] = ProcessThinLTOModule( ProducedBinaries[count] = ProcessThinLTOModule(
*TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList, *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
CacheOptions, SaveTempsDir, count); CacheOptions, DisableCodeGen, SaveTempsDir, count);
}, count); }, count);
count++; count++;
} }

View File

@ -473,6 +473,16 @@ LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
MemBuffer->getBufferSize()}; MemBuffer->getBufferSize()};
} }
void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
lto_bool_t disable) {
unwrap(cg)->disableCodeGen(disable);
}
void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
lto_bool_t CodeGenOnly) {
unwrap(cg)->setCodeGenOnly(CodeGenOnly);
}
void thinlto_debug_options(const char *const *options, int number) { void thinlto_debug_options(const char *const *options, int number) {
// if options were requested, set them // if options were requested, set them
if (number && options) { if (number && options) {
@ -483,7 +493,7 @@ void thinlto_debug_options(const char *const *options, int number) {
} }
} }
bool lto_module_is_thinlto(lto_module_t mod) { lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
return unwrap(mod)->isThinLTO(); return unwrap(mod)->isThinLTO();
} }

View File

@ -61,4 +61,6 @@ thinlto_debug_options
lto_module_is_thinlto lto_module_is_thinlto
thinlto_codegen_add_must_preserve_symbol thinlto_codegen_add_must_preserve_symbol
thinlto_codegen_add_cross_referenced_symbol thinlto_codegen_add_cross_referenced_symbol
thinlto_codegen_set_final_cache_size_relative_to_available_space thinlto_codegen_set_final_cache_size_relative_to_available_space
thinlto_codegen_set_codegen_only
thinlto_codegen_disable_codegen