llvm.org GIT mirror llvm / 4389009
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 Rafael Espindola 6 years ago
12 changed file(s) with 127 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
7272
7373 void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; }
7474
75 void addDSOSymbol(const char* Sym) {
76 DSOSymbols[Sym] = 1;
77 }
78
7579 // To pass options to the driver and optimization passes. These options are
7680 // not necessarily for debugging purpose (The function name is misleading).
7781 // This function should be called before LTOCodeGenerator::compilexxx(),
125129 void applyScopeRestrictions();
126130 void applyRestriction(llvm::GlobalValue &GV,
127131 std::vector &MustPreserveList,
132 std::vector &SymtabList,
128133 llvm::SmallPtrSet &AsmUsed,
129134 llvm::Mangler &Mangler);
130135 bool determineTarget(std::string &errMsg);
137142 bool EmitDwarfDebugInfo;
138143 bool ScopeRestrictionsDone;
139144 lto_codegen_model CodeModel;
145 StringSet DSOSymbols;
140146 StringSet MustPreserveSymbols;
141147 StringSet AsmUndefinedRefs;
142148 llvm::MemoryBuffer *NativeObjectFile;
103103
104104 //===----------------------------------------------------------------------===//
105105 /// createInternalizePass - This pass loops over all of the functions in the
106 /// input module, internalizing all globals (functions and variables) not in the
107 /// given exportList.
106 /// input module, internalizing all globals (functions and variables) it can.
107 ////
108 /// The symbols in \p ExportList are never internalized.
109 ///
110 /// The symbol in DSOList are internalized if it is safe to drop them from
111 /// the symbol table.
112 ///
113 /// For example of the difference, consider a dynamic library being built from
114 /// two translation units. The first one compiled to a native object
115 /// (ELF/MachO/COFF) and second one compiled to IL. Translation unit A has a
116 /// copy of linkonce_odr unnamed_addr function F. The translation unit B has a
117 /// copy of the linkonce_odr unnamed_addr functions F and G.
118 ///
119 /// Assume the linker decides to keep the copy of F in B. This means that LLVM
120 /// must produce F in the object file it passes to the linker, otherwise we
121 /// will have an undefined reference. For G the situation is different. The
122 /// linker puts the function in the DSOList, since it is only wanted for the
123 /// symbol table. With this information internalize can now reason that since
124 /// the function is a linkonce_odr and its address is not important, it can be
125 /// omitted. Any other shared library needing this function will have a copy of
126 /// it.
108127 ///
109128 /// Note that commandline options that are used with the above function are not
110129 /// used now!
111 ModulePass *createInternalizePass(ArrayRef ExportList);
130 ModulePass *createInternalizePass(ArrayRef ExportList,
131 ArrayRef DSOList);
112132 /// createInternalizePass - Same as above, but with an empty exportList.
113133 ModulePass *createInternalizePass();
114134
2828 * @{
2929 */
3030
31 #define LTO_API_VERSION 4
31 #define LTO_API_VERSION 5
3232
3333 typedef enum {
3434 LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
252252 int nargs);
253253
254254 /**
255 * Adds to a list of all global symbols that must exist in the final
256 * generated code. If a function is not listed, it might be
257 * inlined into every usage and optimized away.
255 * Tells LTO optimization passes that this symbol must be preserved
256 * because it is referenced by native code or a command line option.
258257 */
259258 extern void
260259 lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol);
260
261
262 /**
263 * Tells LTO optimization passes that a dynamic shared library is being
264 * built and this symbol may be exported. Unless IR semantics allow the symbol
265 * to be made local to the library, it should remain so it can be exported by
266 * the shared library.
267 */
268 extern void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char *symbol);
261269
262270 /**
263271 * Writes a new object file at the specified path that contains the
309309 void LTOCodeGenerator::
310310 applyRestriction(GlobalValue &GV,
311311 std::vector &MustPreserveList,
312 std::vector &DSOList,
312313 SmallPtrSet &AsmUsed,
313314 Mangler &Mangler) {
314315 SmallString<64> Buffer;
318319 return;
319320 if (MustPreserveSymbols.count(Buffer))
320321 MustPreserveList.push_back(GV.getName().data());
322 if (DSOSymbols.count(Buffer))
323 DSOList.push_back(GV.getName().data());
321324 if (AsmUndefinedRefs.count(Buffer))
322325 AsmUsed.insert(&GV);
323326 }
347350 NULL);
348351 Mangler Mangler(MContext, TargetMach);
349352 std::vector MustPreserveList;
353 std::vector DSOList;
350354 SmallPtrSet AsmUsed;
351355
352356 for (Module::iterator f = mergedModule->begin(),
353357 e = mergedModule->end(); f != e; ++f)
354 applyRestriction(*f, MustPreserveList, AsmUsed, Mangler);
358 applyRestriction(*f, MustPreserveList, DSOList, AsmUsed, Mangler);
355359 for (Module::global_iterator v = mergedModule->global_begin(),
356360 e = mergedModule->global_end(); v != e; ++v)
357 applyRestriction(*v, MustPreserveList, AsmUsed, Mangler);
361 applyRestriction(*v, MustPreserveList, DSOList, AsmUsed, Mangler);
358362 for (Module::alias_iterator a = mergedModule->alias_begin(),
359363 e = mergedModule->alias_end(); a != e; ++a)
360 applyRestriction(*a, MustPreserveList, AsmUsed, Mangler);
364 applyRestriction(*a, MustPreserveList, DSOList, AsmUsed, Mangler);
361365
362366 GlobalVariable *LLVMCompilerUsed =
363367 mergedModule->getGlobalVariable("llvm.compiler.used");
385389 LLVMCompilerUsed->setSection("llvm.metadata");
386390 }
387391
388 passes.add(createInternalizePass(MustPreserveList));
392 passes.add(createInternalizePass(MustPreserveList, DSOList));
389393
390394 // apply scope restrictions
391395 passes.run(*mergedModule);
9797 std::vector Export;
9898 if (AllButMain)
9999 Export.push_back("main");
100 unwrap(PM)->add(createInternalizePass(Export));
100 unwrap(PM)->add(createInternalizePass(Export, None));
101101 }
102102
103103 void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
4343 cl::desc("A list of symbol names to preserve"),
4444 cl::CommaSeparated);
4545
46 static cl::list
47 DSOList("internalize-dso-list", cl::value_desc("list"),
48 cl::desc("A list of symbol names need for a dso symbol table"),
49 cl::CommaSeparated);
50
4651 namespace {
4752 class InternalizePass : public ModulePass {
4853 std::set ExternalNames;
54 std::set DSONames;
4955 public:
5056 static char ID; // Pass identification, replacement for typeid
5157 explicit InternalizePass();
52 explicit InternalizePass(ArrayRef ExportList);
58 explicit InternalizePass(ArrayRef ExportList,
59 ArrayRef DSOList);
5360 void LoadFile(const char *Filename);
5461 virtual bool runOnModule(Module &M);
5562
7077 if (!APIFile.empty()) // If a filename is specified, use it.
7178 LoadFile(APIFile.c_str());
7279 ExternalNames.insert(APIList.begin(), APIList.end());
73 }
74
75 InternalizePass::InternalizePass(ArrayRef ExportList)
80 DSONames.insert(DSOList.begin(), DSOList.end());
81 }
82
83 InternalizePass::InternalizePass(ArrayRef ExportList,
84 ArrayRef DSOList)
7685 : ModulePass(ID){
7786 initializeInternalizePassPass(*PassRegistry::getPassRegistry());
7887 for(ArrayRef::const_iterator itr = ExportList.begin();
7988 itr != ExportList.end(); itr++) {
8089 ExternalNames.insert(*itr);
90 }
91 for(ArrayRef::const_iterator itr = DSOList.begin();
92 itr != DSOList.end(); itr++) {
93 DSONames.insert(*itr);
8194 }
8295 }
8396
98111 }
99112
100113 static bool shouldInternalize(const GlobalValue &GV,
101 const std::set &ExternalNames) {
114 const std::set &ExternalNames,
115 const std::set &DSONames) {
102116 // Function must be defined here
103117 if (GV.isDeclaration())
104118 return false;
115129 if (ExternalNames.count(GV.getName()))
116130 return false;
117131
118 return true;
132 // Not needed for the symbol table?
133 if (!DSONames.count(GV.getName()))
134 return true;
135
136 // Not a linkonce. Someone can depend on it being on the symbol table.
137 if (!GV.hasLinkOnceLinkage())
138 return false;
139
140 // The address is not important, we can hide it.
141 if (GV.hasUnnamedAddr())
142 return true;
143
144 // FIXME: Check if the address is used.
145 return false;
119146 }
120147
121148 bool InternalizePass::runOnModule(Module &M) {
144171 // Mark all functions not in the api as internal.
145172 // FIXME: maybe use private linkage?
146173 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
147 if (!shouldInternalize(*I, ExternalNames))
174 if (!shouldInternalize(*I, ExternalNames, DSONames))
148175 continue;
149176
150177 I->setLinkage(GlobalValue::InternalLinkage);
181208 // FIXME: maybe use private linkage?
182209 for (Module::global_iterator I = M.global_begin(), E = M.global_end();
183210 I != E; ++I) {
184 if (!shouldInternalize(*I, ExternalNames))
211 if (!shouldInternalize(*I, ExternalNames, DSONames))
185212 continue;
186213
187214 I->setLinkage(GlobalValue::InternalLinkage);
193220 // Mark all aliases that are not in the api as internal as well.
194221 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
195222 I != E; ++I) {
196 if (!shouldInternalize(*I, ExternalNames))
223 if (!shouldInternalize(*I, ExternalNames, DSONames))
197224 continue;
198225
199226 I->setLinkage(GlobalValue::InternalLinkage);
209236 return new InternalizePass();
210237 }
211238
212 ModulePass *llvm::createInternalizePass(ArrayRef ExportList) {
213 return new InternalizePass(ExportList);
214 }
239 ModulePass *llvm::createInternalizePass(ArrayRef ExportList,
240 ArrayRef DSOList) {
241 return new InternalizePass(ExportList, DSOList);
242 }
276276 // for a main function. If main is defined, mark all other functions
277277 // internal.
278278 if (Internalize)
279 PM.add(createInternalizePass("main"));
279 PM.add(createInternalizePass("main", None));
280280
281281 // Propagate constants at call sites into the functions they call. This
282282 // opens opportunities for globalopt (and inlining) by substituting function
2626 call void @PR14512()
2727 ret i32 0
2828 }
29
30 ; RUN: llvm-lto -o %t -dso-symbol=zed1 -dso-symbol=zed2 %t1 -disable-opt
31 ; RUN: llvm-nm %t | FileCheck %s -check-prefix=ZED1_AND_ZED2
32 ; ZED1_AND_ZED2: V zed1
33 @zed1 = linkonce_odr global i32 42
34
35 ; ZED1_AND_ZED2: d zed2
36 @zed2 = linkonce_odr unnamed_addr global i32 42
1212 ; -file and -list options should be merged, the apifile contains foo and j
1313 ; RUN: opt < %s -internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s
1414
15 ; Put zed1 and zed2 in the symbol table. If the address is not relevant, we
16 ; internalize them.
17 ; RUN: opt < %s -internalize -internalize-dso-list zed1,zed2 -S | FileCheck --check-prefix=ZED1_AND_ZED2 %s
18
1519 ; ALL: @i = internal global
1620 ; FOO_AND_J: @i = internal global
1721 ; FOO_AND_BAR: @i = internal global
2327 ; FOO_AND_BAR: @j = internal global
2428 ; FOO_J_AND_BAR: @j = global
2529 @j = global i32 0
30
31 ; ZED1_AND_ZED2: @zed1 = linkonce_odr global i32 42
32 @zed1 = linkonce_odr global i32 42
33
34 ; ZED1_AND_ZED2: @zed2 = internal unnamed_addr global i32 42
35 @zed2 = linkonce_odr unnamed_addr global i32 42
2636
2737 ; ALL: define internal void @main() {
2838 ; FOO_AND_J: define internal void @main() {
196196 case LDPT_ADD_SYMBOLS:
197197 add_symbols = tv->tv_u.tv_add_symbols;
198198 break;
199 case LDPT_GET_SYMBOLS:
199 case LDPT_GET_SYMBOLS_V2:
200200 get_symbols = tv->tv_u.tv_get_symbols;
201201 break;
202202 case LDPT_ADD_INPUT_FILE:
385385
386386 if (options::generate_api_file)
387387 api_file << I->syms[i].name << "\n";
388 } else if (I->syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) {
389 lto_codegen_add_dso_symbol(code_gen, I->syms[i].name);
390
391 if (options::generate_api_file)
392 api_file << I->syms[i].name << " dso only\n";
388393 }
389394 }
390395 }
4949 cl::desc("Symbol to export from the resulting object file"),
5050 cl::ZeroOrMore);
5151
52 static cl::list
53 DSOSymbols("dso-symbol",
54 cl::desc("Symbol to put in the symtab in the resulting dso"),
55 cl::ZeroOrMore);
5256
5357 int main(int argc, char **argv) {
5458 // Print a stack trace if we signal out.
116120 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
117121 CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
118122
123 // Add all the dso symbols to the table of symbols to expose.
124 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
125 CodeGen.addDSOSymbol(DSOSymbols[i].c_str());
126
119127 if (!OutputFilename.empty()) {
120128 size_t len = 0;
121129 std::string ErrorInfo;
259259 cg->addMustPreserveSymbol(symbol);
260260 }
261261
262 void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char *symbol) {
263 cg->addDSOSymbol(symbol);
264 }
265
262266 /// lto_codegen_write_merged_modules - Writes a new file at the specified path
263267 /// that contains the merged contents of all modules added so far. Returns true
264268 /// on error (check lto_get_error_message() for details).