diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 89f54b7a7b7..2292f470eba 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 5 +#define LTO_API_VERSION 6 typedef enum { LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ @@ -73,6 +73,11 @@ typedef enum { LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2 } lto_codegen_model; +typedef enum { + LTO_INTERNALIZE_FULL = 0, + LTO_INTERNALIZE_NONE = 1, + LTO_INTERNALIZE_HIDDEN = 2 +} lto_internalize_strategy; /** opaque reference to a loaded object module */ typedef struct LTOModule* lto_module_t; @@ -263,6 +268,14 @@ extern void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, int nargs); +/** + * Sets the strategy to use during internalize. Default strategy is + * LTO_INTERNALIZE_FULL. + */ +extern void +lto_codegen_set_internalize_strategy(lto_code_gen_t cg, + lto_internalize_strategy); + /** * Tells LTO optimization passes that this symbol must be preserved * because it is referenced by native code or a command line option. diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 04d18fd157c..defea4f7ca0 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -70,6 +70,7 @@ struct LTOCodeGenerator { void setTargetOptions(llvm::TargetOptions options); void setDebugInfo(lto_debug_model); void setCodePICModel(lto_codegen_model); + void setInternalizeStrategy(lto_internalize_strategy); void setCpu(const char *mCpu) { MCpu = mCpu; } @@ -114,6 +115,14 @@ struct LTOCodeGenerator { bool disableGVNLoadPRE, std::string &errMsg); + bool shouldInternalize() const { + return InternalizeStrategy != LTO_INTERNALIZE_NONE; + } + + bool shouldOnlyInternalizeHidden() const { + return InternalizeStrategy == LTO_INTERNALIZE_HIDDEN; + } + private: void initializeLTOPasses(); @@ -138,6 +147,7 @@ private: bool EmitDwarfDebugInfo; bool ScopeRestrictionsDone; lto_codegen_model CodeModel; + lto_internalize_strategy InternalizeStrategy; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; llvm::MemoryBuffer *NativeObjectFile; diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 7f51c516b9b..11a0acfc6a4 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -108,14 +108,17 @@ Pass *createPruneEHPass(); //// /// The symbols in \p ExportList are never internalized. /// +/// When OnlyHidden=true, only symbols with hidden visibility are internalized. +/// /// The symbol in DSOList are internalized if it is safe to drop them from /// the symbol table. /// /// Note that commandline options that are used with the above function are not /// used now! -ModulePass *createInternalizePass(ArrayRef ExportList); +ModulePass *createInternalizePass(ArrayRef ExportList, + bool OnlyHidden = false); /// createInternalizePass - Same as above, but with an empty exportList. -ModulePass *createInternalizePass(); +ModulePass *createInternalizePass(bool OnlyHidden = false); //===----------------------------------------------------------------------===// /// createDeadArgEliminationPass - This pass removes arguments from functions diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 59d5a791bea..8d84a8b525e 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -62,7 +62,8 @@ const char* LTOCodeGenerator::getVersionString() { LTOCodeGenerator::LTOCodeGenerator() : Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)), TargetMach(NULL), EmitDwarfDebugInfo(false), ScopeRestrictionsDone(false), - CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), NativeObjectFile(NULL) { + CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), + InternalizeStrategy(LTO_INTERNALIZE_FULL), NativeObjectFile(NULL) { initializeLTOPasses(); } @@ -164,6 +165,18 @@ void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) { llvm_unreachable("Unknown PIC model!"); } +void +LTOCodeGenerator::setInternalizeStrategy(lto_internalize_strategy Strategy) { + switch (Strategy) { + case LTO_INTERNALIZE_FULL: + case LTO_INTERNALIZE_NONE: + case LTO_INTERNALIZE_HIDDEN: + InternalizeStrategy = Strategy; + return; + } + llvm_unreachable("Unknown internalize strategy!"); +} + bool LTOCodeGenerator::writeMergedModules(const char *path, std::string &errMsg) { if (!determineTarget(errMsg)) @@ -377,7 +390,7 @@ static void accumulateAndSortLibcalls(std::vector &Libcalls, } void LTOCodeGenerator::applyScopeRestrictions() { - if (ScopeRestrictionsDone) + if (ScopeRestrictionsDone || !shouldInternalize()) return; Module *mergedModule = Linker.getModule(); @@ -429,7 +442,8 @@ void LTOCodeGenerator::applyScopeRestrictions() { LLVMCompilerUsed->setSection("llvm.metadata"); } - passes.add(createInternalizePass(MustPreserveList)); + passes.add( + createInternalizePass(MustPreserveList, shouldOnlyInternalizeHidden())); // apply scope restrictions passes.run(*mergedModule); diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp index dae69ce0915..775ca968518 100644 --- a/lib/Transforms/IPO/Internalize.cpp +++ b/lib/Transforms/IPO/Internalize.cpp @@ -54,10 +54,11 @@ APIList("internalize-public-api-list", cl::value_desc("list"), namespace { class InternalizePass : public ModulePass { std::set ExternalNames; + bool OnlyHidden; public: static char ID; // Pass identification, replacement for typeid - explicit InternalizePass(); - explicit InternalizePass(ArrayRef ExportList); + explicit InternalizePass(bool OnlyHidden = false); + explicit InternalizePass(ArrayRef ExportList, bool OnlyHidden); void LoadFile(const char *Filename); virtual bool runOnModule(Module &M); @@ -72,16 +73,17 @@ char InternalizePass::ID = 0; INITIALIZE_PASS(InternalizePass, "internalize", "Internalize Global Symbols", false, false) -InternalizePass::InternalizePass() - : ModulePass(ID) { +InternalizePass::InternalizePass(bool OnlyHidden) + : ModulePass(ID), OnlyHidden(OnlyHidden) { initializeInternalizePassPass(*PassRegistry::getPassRegistry()); if (!APIFile.empty()) // If a filename is specified, use it. LoadFile(APIFile.c_str()); ExternalNames.insert(APIList.begin(), APIList.end()); } -InternalizePass::InternalizePass(ArrayRef ExportList) - : ModulePass(ID){ +InternalizePass::InternalizePass(ArrayRef ExportList, + bool OnlyHidden) + : ModulePass(ID), OnlyHidden(OnlyHidden) { initializeInternalizePassPass(*PassRegistry::getPassRegistry()); for(ArrayRef::const_iterator itr = ExportList.begin(); itr != ExportList.end(); itr++) { @@ -106,7 +108,11 @@ void InternalizePass::LoadFile(const char *Filename) { } static bool shouldInternalize(const GlobalValue &GV, - const std::set &ExternalNames) { + const std::set &ExternalNames, + bool OnlyHidden) { + if (OnlyHidden && !GV.hasHiddenVisibility()) + return false; + // Function must be defined here if (GV.isDeclaration()) return false; @@ -155,9 +161,8 @@ bool InternalizePass::runOnModule(Module &M) { } // Mark all functions not in the api as internal. - // FIXME: maybe use private linkage? for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames)) + if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -191,10 +196,9 @@ bool InternalizePass::runOnModule(Module &M) { // Mark all global variables with initializers that are not in the api as // internal as well. - // FIXME: maybe use private linkage? for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames)) + if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -206,7 +210,7 @@ bool InternalizePass::runOnModule(Module &M) { // Mark all aliases that are not in the api as internal as well. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames)) + if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -218,10 +222,11 @@ bool InternalizePass::runOnModule(Module &M) { return Changed; } -ModulePass *llvm::createInternalizePass() { - return new InternalizePass(); +ModulePass *llvm::createInternalizePass(bool OnlyHidden) { + return new InternalizePass(OnlyHidden); } -ModulePass *llvm::createInternalizePass(ArrayRef ExportList) { - return new InternalizePass(ExportList); +ModulePass *llvm::createInternalizePass(ArrayRef ExportList, + bool OnlyHidden) { + return new InternalizePass(ExportList, OnlyHidden); } diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 59b778dcc94..a28257f6ab0 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -252,6 +252,13 @@ void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, // In here only for backwards compatibility. We use MC now. } +/// lto_codegen_set_internalize_strategy - Sets the strategy to use during +/// internalize. +void lto_codegen_set_internalize_strategy(lto_code_gen_t cg, + lto_internalize_strategy strategy) { + cg->setInternalizeStrategy(strategy); +} + /// lto_codegen_add_must_preserve_symbol - Adds to a list of all global symbols /// that must exist in the final generated code. If a function is not listed /// there, it might be inlined into every usage and optimized away.