llvm.org GIT mirror llvm / 32d095c
[ThinLTO] Refactor ODR resolution and internalization (NFC) Move the now index-based ODR resolution and internalization routines out of ThinLTOCodeGenerator.cpp and into either LTO.cpp (index-based analysis) or FunctionImport.cpp (index-driven optimizations). This is to enable usage by other linkers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270698 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
5 changed file(s) with 211 addition(s) and 174 deletion(s). Raw diff Collapse all Expand all
1616 #define LLVM_LTO_LTO_H
1717
1818 #include "llvm/ADT/StringMap.h"
19 #include "llvm/IR/ModuleSummaryIndex.h"
1920
2021 namespace llvm {
2122
4647 return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true);
4748 }
4849 };
50
51
52 /// Resolve Weak and LinkOnce values in the \p Index. Linkage changes recorded
53 /// in the index and the ThinLTO backends must apply the changes to the Module
54 /// via thinLTOResolveWeakForLinkerModule.
55 ///
56 /// This is done for correctness (if value exported, ensure we always
57 /// emit a copy), and compile-time optimization (allow drop of duplicates).
58 void thinLTOResolveWeakForLinkerInIndex(
59 ModuleSummaryIndex &Index,
60 std::function
61 isPrevailing,
62 std::function isExported,
63 std::function
64 recordNewLinkage);
65
66 /// Update the linkages in the given \p Index to mark exported values
67 /// as external and non-exported values as internal. The ThinLTO backends
68 /// must apply the changes to the Module via thinLTOInternalizeModule.
69 void thinLTOInternalizeAndPromoteInIndex(
70 ModuleSummaryIndex &Index,
71 std::function isExported);
72
4973 }
5074
5175 #endif
106106 std::error_code
107107 EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
108108 const StringMap &ImportLists);
109
110 /// Resolve WeakForLinker values in \p TheModule based on the information
111 /// recorded in the summaries during global summary-based analysis.
112 void thinLTOResolveWeakForLinkerModule(Module &TheModule,
113 const GVSummaryMapTy &DefinedGlobals);
114
115 /// Internalize \p TheModule based on the information recorded in the summaries
116 /// during global summary-based analysis.
117 void thinLTOInternalizeModule(Module &TheModule,
118 const GVSummaryMapTy &DefinedGlobals);
109119 }
110120
111121 #endif // LLVM_FUNCTIONIMPORT_H
3838 }
3939 return std::move(ModuleOrErr.get());
4040 }
41
42 static void thinLTOResolveWeakForLinkerGUID(
43 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
44 DenseSet &GlobalInvolvedWithAlias,
45 std::function
46 isPrevailing,
47 std::function isExported,
48 std::function
49 recordNewLinkage) {
50 auto HasMultipleCopies = GVSummaryList.size() > 1;
51
52 for (auto &S : GVSummaryList) {
53 if (GlobalInvolvedWithAlias.count(S.get()))
54 continue;
55 GlobalValue::LinkageTypes OriginalLinkage = S->linkage();
56 if (!GlobalValue::isWeakForLinker(OriginalLinkage))
57 continue;
58 // We need to emit only one of these, the first module will keep it,
59 // but turned into a weak, while the others will drop it when possible.
60 if (!HasMultipleCopies) {
61 // Exported Linkonce needs to be promoted to not be discarded.
62 // FIXME: This should handle LinkOnceAny as well, but that should be a
63 // follow-on to the NFC restructuring:
64 // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage) &&
65 // isExported(S->modulePath(), GUID))
66 // S->setLinkage(GlobalValue::getWeakLinkage(
67 // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
68 if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) &&
69 isExported(S->modulePath(), GUID))
70 S->setLinkage(GlobalValue::WeakODRLinkage);
71 } else if (isPrevailing(GUID, S.get())) {
72 // FIXME: This should handle LinkOnceAny as well, but that should be a
73 // follow-on to the NFC restructuring:
74 // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage))
75 // S->setLinkage(GlobalValue::getWeakLinkage(
76 // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
77 if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))
78 S->setLinkage(GlobalValue::WeakODRLinkage);
79 }
80 // Alias can't be turned into available_externally.
81 else if (!isa(S.get()) &&
82 (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) ||
83 GlobalValue::isWeakODRLinkage(OriginalLinkage)))
84 S->setLinkage(GlobalValue::AvailableExternallyLinkage);
85 if (S->linkage() != OriginalLinkage)
86 recordNewLinkage(S->modulePath(), GUID, S->linkage());
87 }
4188 }
89
90 // Resolve Weak and LinkOnce values in the \p Index.
91 //
92 // We'd like to drop these functions if they are no longer referenced in the
93 // current module. However there is a chance that another module is still
94 // referencing them because of the import. We make sure we always emit at least
95 // one copy.
96 void thinLTOResolveWeakForLinkerInIndex(
97 ModuleSummaryIndex &Index,
98 std::function
99 isPrevailing,
100 std::function isExported,
101 std::function
102 recordNewLinkage) {
103 if (Index.modulePaths().size() == 1)
104 // Nothing to do if we don't have multiple modules
105 return;
106
107 // We won't optimize the globals that are referenced by an alias for now
108 // Ideally we should turn the alias into a global and duplicate the definition
109 // when needed.
110 DenseSet GlobalInvolvedWithAlias;
111 for (auto &I : Index)
112 for (auto &S : I.second)
113 if (auto AS = dyn_cast(S.get()))
114 GlobalInvolvedWithAlias.insert(&AS->getAliasee());
115
116 for (auto &I : Index)
117 thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
118 isPrevailing, isExported, recordNewLinkage);
119 }
120
121 static void thinLTOInternalizeAndPromoteGUID(
122 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
123 std::function isExported) {
124 for (auto &S : GVSummaryList) {
125 if (isExported(S->modulePath(), GUID)) {
126 if (GlobalValue::isLocalLinkage(S->linkage()))
127 S->setLinkage(GlobalValue::ExternalLinkage);
128 } else if (!GlobalValue::isLocalLinkage(S->linkage()))
129 S->setLinkage(GlobalValue::InternalLinkage);
130 }
131 }
132
133 // Update the linkages in the given \p Index to mark exported values
134 // as external and non-exported values as internal.
135 void thinLTOInternalizeAndPromoteInIndex(
136 ModuleSummaryIndex &Index,
137 std::function isExported) {
138 for (auto &I : Index)
139 thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
140 }
141 }
127127 }
128128 }
129129
130 static void thinLTOResolveWeakForLinkerGUID(
131 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
132 DenseSet &GlobalInvolvedWithAlias,
133 std::function
134 isPrevailing,
135 std::function isExported,
136 std::function
137 recordNewLinkage) {
138 auto HasMultipleCopies = GVSummaryList.size() > 1;
139
140 for (auto &S : GVSummaryList) {
141 if (GlobalInvolvedWithAlias.count(S.get()))
142 continue;
143 GlobalValue::LinkageTypes OriginalLinkage = S->linkage();
144 if (!GlobalValue::isWeakForLinker(OriginalLinkage))
145 continue;
146 // We need to emit only one of these, the first module will keep it,
147 // but turned into a weak, while the others will drop it when possible.
148 if (!HasMultipleCopies) {
149 // Exported Linkonce needs to be promoted to not be discarded.
150 // FIXME: This should handle LinkOnceAny as well, but that should be a
151 // follow-on to the NFC restructuring:
152 // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage) &&
153 // isExported(S->modulePath(), GUID))
154 // S->setLinkage(GlobalValue::getWeakLinkage(
155 // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
156 if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) &&
157 isExported(S->modulePath(), GUID))
158 S->setLinkage(GlobalValue::WeakODRLinkage);
159 } else if (isPrevailing(GUID, S.get())) {
160 // FIXME: This should handle LinkOnceAny as well, but that should be a
161 // follow-on to the NFC restructuring:
162 // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage))
163 // S->setLinkage(GlobalValue::getWeakLinkage(
164 // GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
165 if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))
166 S->setLinkage(GlobalValue::WeakODRLinkage);
167 }
168 // Alias can't be turned into available_externally.
169 else if (!isa(S.get()) &&
170 (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) ||
171 GlobalValue::isWeakODRLinkage(OriginalLinkage)))
172 S->setLinkage(GlobalValue::AvailableExternallyLinkage);
173 if (S->linkage() != OriginalLinkage)
174 recordNewLinkage(S->modulePath(), GUID, S->linkage());
175 }
176 }
177
178 // Resolve Weak and LinkOnce values in the \p Index.
179 //
180 // We'd like to drop these functions if they are no longer referenced in the
181 // current module. However there is a chance that another module is still
182 // referencing them because of the import. We make sure we always emit at least
183 // one copy.
184 void thinLTOResolveWeakForLinkerInIndex(
185 ModuleSummaryIndex &Index,
186 std::function
187 isPrevailing,
188 std::function isExported,
189 std::function
190 recordNewLinkage) {
191 if (Index.modulePaths().size() == 1)
192 // Nothing to do if we don't have multiple modules
193 return;
194
195 // We won't optimize the globals that are referenced by an alias for now
196 // Ideally we should turn the alias into a global and duplicate the definition
197 // when needed.
198 DenseSet GlobalInvolvedWithAlias;
199 for (auto &I : Index)
200 for (auto &S : I.second)
201 if (auto AS = dyn_cast(S.get()))
202 GlobalInvolvedWithAlias.insert(&AS->getAliasee());
203
204 for (auto &I : Index)
205 thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
206 isPrevailing, isExported, recordNewLinkage);
207 }
208
209 /// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
210 void thinLTOResolveWeakForLinkerModule(Module &TheModule,
211 const GVSummaryMapTy &DefinedGlobals) {
212 auto updateLinkage = [&](GlobalValue &GV) {
213 if (!GlobalValue::isWeakForLinker(GV.getLinkage()))
214 return;
215 // See if the global summary analysis computed a new resolved linkage.
216 const auto &GS = DefinedGlobals.find(GV.getGUID());
217 if (GS == DefinedGlobals.end())
218 return;
219 auto NewLinkage = GS->second->linkage();
220 if (NewLinkage == GV.getLinkage())
221 return;
222 DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
223 << GV.getLinkage() << " to " << NewLinkage << "\n");
224 GV.setLinkage(NewLinkage);
225 };
226
227 // Process functions and global now
228 for (auto &GV : TheModule)
229 updateLinkage(GV);
230 for (auto &GV : TheModule.globals())
231 updateLinkage(GV);
232 for (auto &GV : TheModule.aliases())
233 updateLinkage(GV);
234 }
235
236130 static StringMap
237131 generateModuleMap(const std::vector &Modules) {
238132 StringMap ModuleMap;
281175 PMB.populateThinLTOPassManager(PM);
282176
283177 PM.run(TheModule);
284 }
285
286 static void thinLTOInternalizeAndPromoteGUID(
287 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
288 std::function isExported) {
289 for (auto &S : GVSummaryList) {
290 if (isExported(S->modulePath(), GUID)) {
291 if (GlobalValue::isLocalLinkage(S->linkage()))
292 S->setLinkage(GlobalValue::ExternalLinkage);
293 } else if (!GlobalValue::isLocalLinkage(S->linkage()))
294 S->setLinkage(GlobalValue::InternalLinkage);
295 }
296 }
297
298 // Update the linkages in the given \p Index to mark exported values
299 // as external and non-exported values as internal.
300 void thinLTOInternalizeAndPromoteInIndex(
301 ModuleSummaryIndex &Index,
302 std::function isExported) {
303 for (auto &I : Index)
304 thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
305 }
306
307 // Run internalization on \p TheModule based on symmary analysis.
308 void thinLTOInternalizeModule(Module &TheModule,
309 const GVSummaryMapTy &DefinedGlobals) {
310 // Parse inline ASM and collect the list of symbols that are not defined in
311 // the current module.
312 StringSet<> AsmUndefinedRefs;
313 object::IRObjectFile::CollectAsmUndefinedRefs(
314 Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(),
315 [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
316 if (Flags & object::BasicSymbolRef::SF_Undefined)
317 AsmUndefinedRefs.insert(Name);
318 });
319
320 // Declare a callback for the internalize pass that will ask for every
321 // candidate GlobalValue if it can be internalized or not.
322 auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
323 // Can't be internalized if referenced in inline asm.
324 if (AsmUndefinedRefs.count(GV.getName()))
325 return true;
326
327 // Lookup the linkage recorded in the summaries during global analysis.
328 const auto &GS = DefinedGlobals.find(GV.getGUID());
329 GlobalValue::LinkageTypes Linkage;
330 if (GS == DefinedGlobals.end()) {
331 // Must have been promoted (possibly conservatively). Find original
332 // name so that we can access the correct summary and see if it can
333 // be internalized again.
334 // FIXME: Eventually we should control promotion instead of promoting
335 // and internalizing again.
336 StringRef OrigName =
337 ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
338 std::string OrigId = GlobalValue::getGlobalIdentifier(
339 OrigName, GlobalValue::InternalLinkage,
340 TheModule.getSourceFileName());
341 const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
342 assert(GS != DefinedGlobals.end());
343 Linkage = GS->second->linkage();
344 } else
345 Linkage = GS->second->linkage();
346 return !GlobalValue::isLocalLinkage(Linkage);
347 };
348
349 // FIXME: See if we can just internalize directly here via linkage changes
350 // based on the index, rather than invoking internalizeModule.
351 llvm::internalizeModule(TheModule, MustPreserveGV);
352178 }
353179
354180 // Convert the PreservedSymbols map from "Name" based to "GUID" based.
1515 #include "llvm/ADT/SmallVector.h"
1616 #include "llvm/ADT/Statistic.h"
1717 #include "llvm/ADT/StringSet.h"
18 #include "llvm/ADT/Triple.h"
1819 #include "llvm/IR/AutoUpgrade.h"
1920 #include "llvm/IR/DiagnosticPrinter.h"
2021 #include "llvm/IR/IntrinsicInst.h"
2122 #include "llvm/IR/Module.h"
2223 #include "llvm/IRReader/IRReader.h"
2324 #include "llvm/Linker/Linker.h"
25 #include "llvm/Object/IRObjectFile.h"
2426 #include "llvm/Object/ModuleSummaryIndexObjectFile.h"
2527 #include "llvm/Support/CommandLine.h"
2628 #include "llvm/Support/Debug.h"
2729 #include "llvm/Support/SourceMgr.h"
30 #include "llvm/Transforms/IPO/Internalize.h"
2831 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
2932
3033 #define DEBUG_TYPE "function-import"
459462 return std::error_code();
460463 }
461464
465 /// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
466 void llvm::thinLTOResolveWeakForLinkerModule(
467 Module &TheModule, const GVSummaryMapTy &DefinedGlobals) {
468 auto updateLinkage = [&](GlobalValue &GV) {
469 if (!GlobalValue::isWeakForLinker(GV.getLinkage()))
470 return;
471 // See if the global summary analysis computed a new resolved linkage.
472 const auto &GS = DefinedGlobals.find(GV.getGUID());
473 if (GS == DefinedGlobals.end())
474 return;
475 auto NewLinkage = GS->second->linkage();
476 if (NewLinkage == GV.getLinkage())
477 return;
478 DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
479 << GV.getLinkage() << " to " << NewLinkage << "\n");
480 GV.setLinkage(NewLinkage);
481 };
482
483 // Process functions and global now
484 for (auto &GV : TheModule)
485 updateLinkage(GV);
486 for (auto &GV : TheModule.globals())
487 updateLinkage(GV);
488 for (auto &GV : TheModule.aliases())
489 updateLinkage(GV);
490 }
491
492 /// Run internalization on \p TheModule based on symmary analysis.
493 void llvm::thinLTOInternalizeModule(Module &TheModule,
494 const GVSummaryMapTy &DefinedGlobals) {
495 // Parse inline ASM and collect the list of symbols that are not defined in
496 // the current module.
497 StringSet<> AsmUndefinedRefs;
498 object::IRObjectFile::CollectAsmUndefinedRefs(
499 Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(),
500 [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
501 if (Flags & object::BasicSymbolRef::SF_Undefined)
502 AsmUndefinedRefs.insert(Name);
503 });
504
505 // Declare a callback for the internalize pass that will ask for every
506 // candidate GlobalValue if it can be internalized or not.
507 auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
508 // Can't be internalized if referenced in inline asm.
509 if (AsmUndefinedRefs.count(GV.getName()))
510 return true;
511
512 // Lookup the linkage recorded in the summaries during global analysis.
513 const auto &GS = DefinedGlobals.find(GV.getGUID());
514 GlobalValue::LinkageTypes Linkage;
515 if (GS == DefinedGlobals.end()) {
516 // Must have been promoted (possibly conservatively). Find original
517 // name so that we can access the correct summary and see if it can
518 // be internalized again.
519 // FIXME: Eventually we should control promotion instead of promoting
520 // and internalizing again.
521 StringRef OrigName =
522 ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
523 std::string OrigId = GlobalValue::getGlobalIdentifier(
524 OrigName, GlobalValue::InternalLinkage,
525 TheModule.getSourceFileName());
526 const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
527 assert(GS != DefinedGlobals.end());
528 Linkage = GS->second->linkage();
529 } else
530 Linkage = GS->second->linkage();
531 return !GlobalValue::isLocalLinkage(Linkage);
532 };
533
534 // FIXME: See if we can just internalize directly here via linkage changes
535 // based on the index, rather than invoking internalizeModule.
536 llvm::internalizeModule(TheModule, MustPreserveGV);
537 }
538
462539 // Automatically import functions in Module \p DestModule based on the summaries
463540 // index.
464541 //