From 438900938c3ac9d7fac2dd5d2c85ca4b9b2e35f7 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 3 Oct 2013 18:29:09 +0000 Subject: Optimize linkonce_odr unnamed_addr functions during LTO. Generalize the API so we can distinguish symbols that are needed just for a DSO symbol table from those that are used from some native .o. The symbols that are only wanted for the dso symbol table can be dropped if llvm can prove every other dso has a copy (linkonce_odr) and the address is not important (unnamed_addr). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191922 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/IPO.cpp | 2 +- lib/Transforms/IPO/Internalize.cpp | 46 +++++++++++++++++++++++++------ lib/Transforms/IPO/PassManagerBuilder.cpp | 2 +- 3 files changed, 39 insertions(+), 11 deletions(-) (limited to 'lib/Transforms') diff --git a/lib/Transforms/IPO/IPO.cpp b/lib/Transforms/IPO/IPO.cpp index 5d563d8bbf..5f26bac2c8 100644 --- a/lib/Transforms/IPO/IPO.cpp +++ b/lib/Transforms/IPO/IPO.cpp @@ -98,7 +98,7 @@ void LLVMAddInternalizePass(LLVMPassManagerRef PM, unsigned AllButMain) { std::vector Export; if (AllButMain) Export.push_back("main"); - unwrap(PM)->add(createInternalizePass(Export)); + unwrap(PM)->add(createInternalizePass(Export, None)); } void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) { diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp index f2feacc0b6..f20a7bd92f 100644 --- a/lib/Transforms/IPO/Internalize.cpp +++ b/lib/Transforms/IPO/Internalize.cpp @@ -44,13 +44,20 @@ APIList("internalize-public-api-list", cl::value_desc("list"), cl::desc("A list of symbol names to preserve"), cl::CommaSeparated); +static cl::list +DSOList("internalize-dso-list", cl::value_desc("list"), + cl::desc("A list of symbol names need for a dso symbol table"), + cl::CommaSeparated); + namespace { class InternalizePass : public ModulePass { std::set ExternalNames; + std::set DSONames; public: static char ID; // Pass identification, replacement for typeid explicit InternalizePass(); - explicit InternalizePass(ArrayRef ExportList); + explicit InternalizePass(ArrayRef ExportList, + ArrayRef DSOList); void LoadFile(const char *Filename); virtual bool runOnModule(Module &M); @@ -71,15 +78,21 @@ InternalizePass::InternalizePass() if (!APIFile.empty()) // If a filename is specified, use it. LoadFile(APIFile.c_str()); ExternalNames.insert(APIList.begin(), APIList.end()); + DSONames.insert(DSOList.begin(), DSOList.end()); } -InternalizePass::InternalizePass(ArrayRef ExportList) +InternalizePass::InternalizePass(ArrayRef ExportList, + ArrayRef DSOList) : ModulePass(ID){ initializeInternalizePassPass(*PassRegistry::getPassRegistry()); for(ArrayRef::const_iterator itr = ExportList.begin(); itr != ExportList.end(); itr++) { ExternalNames.insert(*itr); } + for(ArrayRef::const_iterator itr = DSOList.begin(); + itr != DSOList.end(); itr++) { + DSONames.insert(*itr); + } } void InternalizePass::LoadFile(const char *Filename) { @@ -99,7 +112,8 @@ void InternalizePass::LoadFile(const char *Filename) { } static bool shouldInternalize(const GlobalValue &GV, - const std::set &ExternalNames) { + const std::set &ExternalNames, + const std::set &DSONames) { // Function must be defined here if (GV.isDeclaration()) return false; @@ -116,7 +130,20 @@ static bool shouldInternalize(const GlobalValue &GV, if (ExternalNames.count(GV.getName())) return false; - return true; + // Not needed for the symbol table? + if (!DSONames.count(GV.getName())) + return true; + + // Not a linkonce. Someone can depend on it being on the symbol table. + if (!GV.hasLinkOnceLinkage()) + return false; + + // The address is not important, we can hide it. + if (GV.hasUnnamedAddr()) + return true; + + // FIXME: Check if the address is used. + return false; } bool InternalizePass::runOnModule(Module &M) { @@ -145,7 +172,7 @@ 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, DSONames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -182,7 +209,7 @@ bool InternalizePass::runOnModule(Module &M) { // 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, DSONames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -194,7 +221,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, DSONames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -210,6 +237,7 @@ ModulePass *llvm::createInternalizePass() { return new InternalizePass(); } -ModulePass *llvm::createInternalizePass(ArrayRef ExportList) { - return new InternalizePass(ExportList); +ModulePass *llvm::createInternalizePass(ArrayRef ExportList, + ArrayRef DSOList) { + return new InternalizePass(ExportList, DSOList); } diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp index 2008c5d65e..b9660fab78 100644 --- a/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -277,7 +277,7 @@ void PassManagerBuilder::populateLTOPassManager(PassManagerBase &PM, // for a main function. If main is defined, mark all other functions // internal. if (Internalize) - PM.add(createInternalizePass("main")); + PM.add(createInternalizePass("main", None)); // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function -- cgit v1.2.3