From 69e4dd1b12f6f880b1d853805d03a04a490be5f5 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 3 Feb 2015 18:39:15 +0000 Subject: [PATCH] [LTO API] split lto_codegen_compile to lto_codegen_optimize and lto_codegen_compile_optimized. Also add lto_api_version. Before this commit, we can only dump the optimized bitcode after running lto_codegen_compile, but it includes some impacts of running codegen passes, one example is StackProtector pass. We will get assertion failure when running llc on the optimized bitcode, because StackProtector is effectively run twice. After splitting lto_codegen_compile, the linker can choose to dump the bitcode before running lto_codegen_compile_optimized. lto_api_version is added so ld64 can check for runtime-availability of the new API. rdar://19565500 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228000 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm-c/lto.h | 39 +++++++++++++- include/llvm/LTO/LTOCodeGenerator.h | 17 +++++-- lib/LTO/LTOCodeGenerator.cpp | 79 +++++++++++++++++++---------- tools/lto/lto.cpp | 20 ++++++++ tools/lto/lto.exports | 3 ++ 5 files changed, 128 insertions(+), 30 deletions(-) diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 3f30d6d535d..3aaf818e3df 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 11 +#define LTO_API_VERSION 12 /** * \since prior to LTO_API_VERSION=3 @@ -464,6 +464,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized. + * * On success returns a pointer to a generated mach-o/ELF buffer and * length set to the buffer size. The buffer is owned by the * lto_code_gen_t and will be freed when lto_codegen_dispose() @@ -477,6 +479,9 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized (instead + * of returning a generated mach-o/ELF buffer, it writes to a file). + * * The name of the file is written to name. Returns true on error. * * \since LTO_API_VERSION=5 @@ -484,6 +489,38 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); +/** + * Runs optimization for the merged module. Returns true on error. + * + * \since LTO_API_VERSION=12 + */ +extern lto_bool_t +lto_codegen_optimize(lto_code_gen_t cg); + +/** + * Generates code for the optimized merged module into one native object file. + * It will not run any IR optimizations on the merged module. + * + * On success returns a pointer to a generated mach-o/ELF buffer and length set + * to the buffer size. The buffer is owned by the lto_code_gen_t and will be + * freed when lto_codegen_dispose() is called, or + * lto_codegen_compile_optimized() is called again. On failure, returns NULL + * (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=12 + */ +extern const void* +lto_codegen_compile_optimized(lto_code_gen_t cg, size_t* length); + +/** + * Returns the runtime API version. + * + * \since LTO_API_VERSION=12 + */ +extern unsigned int +lto_api_version() { + return LTO_API_VERSION; +} /** * Sets options to help debug codegen bugs. diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 0c9ce4a54f0..ab307bf2d0c 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -117,6 +117,18 @@ struct LTOCodeGenerator { bool disableVectorization, std::string &errMsg); + // Optimizes the merged module. Returns true on success. + bool optimize(bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); + + // Compiles the merged optimized module into a single object file. It brings + // the object to a buffer, and returns the buffer to the caller. Return NULL + // if the compilation was not successful. + const void *compileOptimized(size_t *length, std::string &errMsg); + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); LLVMContext &getContext() { return Context; } @@ -124,9 +136,8 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); - bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, bool disableVectorization, - std::string &errMsg); + bool compileOptimized(raw_ostream &out, std::string &errMsg); + bool compileOptimizedToFile(const char **name, std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(GlobalValue &GV, ArrayRef Libcalls, std::vector &MustPreserveList, diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 27b87764065..f37d0a9fa44 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -202,12 +202,8 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, return true; } -bool LTOCodeGenerator::compile_to_file(const char** name, - bool disableOpt, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string& errMsg) { +bool LTOCodeGenerator::compileOptimizedToFile(const char **name, + std::string &errMsg) { // make unique temp .o file to put generated object file SmallString<128> Filename; int FD; @@ -221,9 +217,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, // generate object file tool_output_file objFile(Filename.c_str(), FD); - bool genResult = - generateObjectFile(objFile.os(), disableOpt, disableInline, - disableGVNLoadPRE, disableVectorization, errMsg); + bool genResult = compileOptimized(objFile.os(), errMsg); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); @@ -242,15 +236,10 @@ bool LTOCodeGenerator::compile_to_file(const char** name, return true; } -const void* LTOCodeGenerator::compile(size_t* length, - bool disableOpt, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string& errMsg) { +const void *LTOCodeGenerator::compileOptimized(size_t *length, + std::string &errMsg) { const char *name; - if (!compile_to_file(&name, disableOpt, disableInline, disableGVNLoadPRE, - disableVectorization, errMsg)) + if (!compileOptimizedToFile(&name, errMsg)) return nullptr; // read .o file into memory buffer @@ -273,6 +262,33 @@ const void* LTOCodeGenerator::compile(size_t* length, return NativeObjectFile->getBufferStart(); } + +bool LTOCodeGenerator::compile_to_file(const char **name, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg) { + if (!optimize(disableOpt, disableInline, disableGVNLoadPRE, + disableVectorization, errMsg)) + return false; + + return compileOptimizedToFile(name, errMsg); +} + +const void* LTOCodeGenerator::compile(size_t *length, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg) { + if (!optimize(disableOpt, disableInline, disableGVNLoadPRE, + disableVectorization, errMsg)) + return nullptr; + + return compileOptimized(length, errMsg); +} + bool LTOCodeGenerator::determineTarget(std::string &errMsg) { if (TargetMach) return true; @@ -469,12 +485,11 @@ void LTOCodeGenerator::applyScopeRestrictions() { } /// Optimize merged modules using various IPO passes -bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, - bool DisableOpt, - bool DisableInline, - bool DisableGVNLoadPRE, - bool DisableVectorization, - std::string &errMsg) { +bool LTOCodeGenerator::optimize(bool DisableOpt, + bool DisableInline, + bool DisableGVNLoadPRE, + bool DisableVectorization, + std::string &errMsg) { if (!this->determineTarget(errMsg)) return false; @@ -508,6 +523,21 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, PMB.populateLTOPassManager(passes); + // Run our queue of passes all at once now, efficiently. + passes.run(*mergedModule); + + return true; +} + +bool LTOCodeGenerator::compileOptimized(raw_ostream &out, std::string &errMsg) { + if (!this->determineTarget(errMsg)) + return false; + + Module *mergedModule = IRLinker.getModule(); + + // Mark which symbols can not be internalized + this->applyScopeRestrictions(); + PassManager codeGenPasses; codeGenPasses.add(new DataLayoutPass()); @@ -524,9 +554,6 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, return false; } - // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); - // Run the code generator, and write assembly file codeGenPasses.run(*mergedModule); diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 74e0dbe5e37..80dca6b4d46 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -296,6 +296,26 @@ const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { sLastErrorString); } +bool lto_codegen_optimize(lto_code_gen_t cg) { + if (!parsedOptions) { + unwrap(cg)->parseCodeGenDebugOptions(); + lto_add_attrs(cg); + parsedOptions = true; + } + return !unwrap(cg)->optimize(DisableOpt, DisableInline, + DisableGVNLoadPRE, DisableLTOVectorization, + sLastErrorString); +} + +const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) { + if (!parsedOptions) { + unwrap(cg)->parseCodeGenDebugOptions(); + lto_add_attrs(cg); + parsedOptions = true; + } + return unwrap(cg)->compileOptimized(length, sLastErrorString); +} + bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { if (!parsedOptions) { unwrap(cg)->parseCodeGenDebugOptions(); diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index f6ceaac74d1..9ef60772fb8 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -22,6 +22,7 @@ lto_module_is_object_file_for_target lto_module_is_object_file_in_memory lto_module_is_object_file_in_memory_for_target lto_module_dispose +lto_api_version lto_codegen_set_diagnostic_handler lto_codegen_add_module lto_codegen_add_must_preserve_symbol @@ -37,6 +38,8 @@ lto_codegen_set_assembler_args lto_codegen_set_assembler_path lto_codegen_set_cpu lto_codegen_compile_to_file +lto_codegen_optimize +lto_codegen_compile_optimized LLVMCreateDisasm LLVMCreateDisasmCPU LLVMDisasmDispose