xref: /llvm-project-15.0.7/llvm/lib/LTO/LTO.cpp (revision 94eb010f)
1 //===-LTO.cpp - LLVM Link Time Optimizer ----------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements functions and classes used to support LTO.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/LTO/LTO.h"
15 #include "llvm/Bitcode/ReaderWriter.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 namespace llvm {
21 
22 // Simple helper to load a module from bitcode
23 std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer,
24                                              LLVMContext &Context, bool Lazy) {
25   SMDiagnostic Err;
26   ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
27   if (Lazy) {
28     ModuleOrErr =
29         getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer, false), Context,
30                              /* ShouldLazyLoadMetadata */ Lazy);
31   } else {
32     ModuleOrErr = parseBitcodeFile(Buffer, Context);
33   }
34   if (std::error_code EC = ModuleOrErr.getError()) {
35     Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
36                        EC.message());
37     Err.print("ThinLTO", errs());
38     report_fatal_error("Can't load module, abort.");
39   }
40   return std::move(ModuleOrErr.get());
41 }
42 
43 static void thinLTOResolveWeakForLinkerGUID(
44     GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
45     DenseSet<GlobalValueSummary *> &GlobalInvolvedWithAlias,
46     std::function<bool(GlobalValue::GUID, const GlobalValueSummary *)>
47         isPrevailing,
48     std::function<bool(StringRef, GlobalValue::GUID)> isExported,
49     std::function<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
50         recordNewLinkage) {
51   auto HasMultipleCopies = GVSummaryList.size() > 1;
52 
53   for (auto &S : GVSummaryList) {
54     if (GlobalInvolvedWithAlias.count(S.get()))
55       continue;
56     GlobalValue::LinkageTypes OriginalLinkage = S->linkage();
57     if (!GlobalValue::isWeakForLinker(OriginalLinkage))
58       continue;
59     // We need to emit only one of these, the first module will keep it,
60     // but turned into a weak, while the others will drop it when possible.
61     if (!HasMultipleCopies) {
62       // Exported Linkonce needs to be promoted to not be discarded.
63       // FIXME: This should handle LinkOnceAny as well, but that should be a
64       // follow-on to the NFC restructuring:
65       // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage) &&
66       //     isExported(S->modulePath(), GUID))
67       //   S->setLinkage(GlobalValue::getWeakLinkage(
68       //       GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
69       if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) &&
70           isExported(S->modulePath(), GUID))
71         S->setLinkage(GlobalValue::WeakODRLinkage);
72     } else if (isPrevailing(GUID, S.get())) {
73       // FIXME: This should handle LinkOnceAny as well, but that should be a
74       // follow-on to the NFC restructuring:
75       // if (GlobalValue::isLinkOnceLinkage(OriginalLinkage))
76       //   S->setLinkage(GlobalValue::getWeakLinkage(
77       //       GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
78       if (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))
79         S->setLinkage(GlobalValue::WeakODRLinkage);
80     }
81     // Alias can't be turned into available_externally.
82     else if (!isa<AliasSummary>(S.get()) &&
83              (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) ||
84               GlobalValue::isWeakODRLinkage(OriginalLinkage)))
85       S->setLinkage(GlobalValue::AvailableExternallyLinkage);
86     if (S->linkage() != OriginalLinkage)
87       recordNewLinkage(S->modulePath(), GUID, S->linkage());
88   }
89 }
90 
91 // Resolve Weak and LinkOnce values in the \p Index.
92 //
93 // We'd like to drop these functions if they are no longer referenced in the
94 // current module. However there is a chance that another module is still
95 // referencing them because of the import. We make sure we always emit at least
96 // one copy.
97 void thinLTOResolveWeakForLinkerInIndex(
98     ModuleSummaryIndex &Index,
99     std::function<bool(GlobalValue::GUID, const GlobalValueSummary *)>
100         isPrevailing,
101     std::function<bool(StringRef, GlobalValue::GUID)> isExported,
102     std::function<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
103         recordNewLinkage) {
104   if (Index.modulePaths().size() == 1)
105     // Nothing to do if we don't have multiple modules
106     return;
107 
108   // We won't optimize the globals that are referenced by an alias for now
109   // Ideally we should turn the alias into a global and duplicate the definition
110   // when needed.
111   DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
112   for (auto &I : Index)
113     for (auto &S : I.second)
114       if (auto AS = dyn_cast<AliasSummary>(S.get()))
115         GlobalInvolvedWithAlias.insert(&AS->getAliasee());
116 
117   for (auto &I : Index)
118     thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
119                                     isPrevailing, isExported, recordNewLinkage);
120 }
121 
122 static void thinLTOInternalizeAndPromoteGUID(
123     GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
124     std::function<bool(StringRef, GlobalValue::GUID)> isExported) {
125   for (auto &S : GVSummaryList) {
126     if (isExported(S->modulePath(), GUID)) {
127       if (GlobalValue::isLocalLinkage(S->linkage()))
128         S->setLinkage(GlobalValue::ExternalLinkage);
129     } else if (!GlobalValue::isLocalLinkage(S->linkage()))
130       S->setLinkage(GlobalValue::InternalLinkage);
131   }
132 }
133 
134 // Update the linkages in the given \p Index to mark exported values
135 // as external and non-exported values as internal.
136 void thinLTOInternalizeAndPromoteInIndex(
137     ModuleSummaryIndex &Index,
138     std::function<bool(StringRef, GlobalValue::GUID)> isExported) {
139   for (auto &I : Index)
140     thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
141 }
142 }
143