Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- llvm/Transforms/IPO/FunctionImport.h - ThinLTO importing -*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | |||
9 | #ifndef LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H |
||
10 | #define LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H |
||
11 | |||
12 | #include "llvm/ADT/DenseSet.h" |
||
13 | #include "llvm/ADT/StringMap.h" |
||
14 | #include "llvm/ADT/StringRef.h" |
||
15 | #include "llvm/IR/GlobalValue.h" |
||
16 | #include "llvm/IR/ModuleSummaryIndex.h" |
||
17 | #include "llvm/IR/PassManager.h" |
||
18 | #include "llvm/Support/Error.h" |
||
19 | #include <functional> |
||
20 | #include <map> |
||
21 | #include <memory> |
||
22 | #include <string> |
||
23 | #include <system_error> |
||
24 | #include <unordered_set> |
||
25 | #include <utility> |
||
26 | |||
27 | namespace llvm { |
||
28 | |||
29 | class Module; |
||
30 | |||
31 | /// The function importer is automatically importing function from other modules |
||
32 | /// based on the provided summary informations. |
||
33 | class FunctionImporter { |
||
34 | public: |
||
35 | /// Set of functions to import from a source module. Each entry is a set |
||
36 | /// containing all the GUIDs of all functions to import for a source module. |
||
37 | using FunctionsToImportTy = std::unordered_set<GlobalValue::GUID>; |
||
38 | |||
39 | /// The different reasons selectCallee will chose not to import a |
||
40 | /// candidate. |
||
41 | enum ImportFailureReason { |
||
42 | None, |
||
43 | // We can encounter a global variable instead of a function in rare |
||
44 | // situations with SamplePGO. See comments where this failure type is |
||
45 | // set for more details. |
||
46 | GlobalVar, |
||
47 | // Found to be globally dead, so we don't bother importing. |
||
48 | NotLive, |
||
49 | // Instruction count over the current threshold. |
||
50 | TooLarge, |
||
51 | // Don't import something with interposable linkage as we can't inline it |
||
52 | // anyway. |
||
53 | InterposableLinkage, |
||
54 | // Generally we won't end up failing due to this reason, as we expect |
||
55 | // to find at least one summary for the GUID that is global or a local |
||
56 | // in the referenced module for direct calls. |
||
57 | LocalLinkageNotInModule, |
||
58 | // This corresponds to the NotEligibleToImport being set on the summary, |
||
59 | // which can happen in a few different cases (e.g. local that can't be |
||
60 | // renamed or promoted because it is referenced on a llvm*.used variable). |
||
61 | NotEligible, |
||
62 | // This corresponds to NoInline being set on the function summary, |
||
63 | // which will happen if it is known that the inliner will not be able |
||
64 | // to inline the function (e.g. it is marked with a NoInline attribute). |
||
65 | NoInline |
||
66 | }; |
||
67 | |||
68 | /// Information optionally tracked for candidates the importer decided |
||
69 | /// not to import. Used for optional stat printing. |
||
70 | struct ImportFailureInfo { |
||
71 | // The ValueInfo corresponding to the candidate. We save an index hash |
||
72 | // table lookup for each GUID by stashing this here. |
||
73 | ValueInfo VI; |
||
74 | // The maximum call edge hotness for all failed imports of this candidate. |
||
75 | CalleeInfo::HotnessType MaxHotness; |
||
76 | // most recent reason for failing to import (doesn't necessarily correspond |
||
77 | // to the attempt with the maximum hotness). |
||
78 | ImportFailureReason Reason; |
||
79 | // The number of times we tried to import candidate but failed. |
||
80 | unsigned Attempts; |
||
81 | ImportFailureInfo(ValueInfo VI, CalleeInfo::HotnessType MaxHotness, |
||
82 | ImportFailureReason Reason, unsigned Attempts) |
||
83 | : VI(VI), MaxHotness(MaxHotness), Reason(Reason), Attempts(Attempts) {} |
||
84 | }; |
||
85 | |||
86 | /// Map of callee GUID considered for import into a given module to a pair |
||
87 | /// consisting of the largest threshold applied when deciding whether to |
||
88 | /// import it and, if we decided to import, a pointer to the summary instance |
||
89 | /// imported. If we decided not to import, the summary will be nullptr. |
||
90 | using ImportThresholdsTy = |
||
91 | DenseMap<GlobalValue::GUID, |
||
92 | std::tuple<unsigned, const GlobalValueSummary *, |
||
93 | std::unique_ptr<ImportFailureInfo>>>; |
||
94 | |||
95 | /// The map contains an entry for every module to import from, the key being |
||
96 | /// the module identifier to pass to the ModuleLoader. The value is the set of |
||
97 | /// functions to import. |
||
98 | using ImportMapTy = StringMap<FunctionsToImportTy>; |
||
99 | |||
100 | /// The set contains an entry for every global value the module exports. |
||
101 | using ExportSetTy = DenseSet<ValueInfo>; |
||
102 | |||
103 | /// A function of this type is used to load modules referenced by the index. |
||
104 | using ModuleLoaderTy = |
||
105 | std::function<Expected<std::unique_ptr<Module>>(StringRef Identifier)>; |
||
106 | |||
107 | /// Create a Function Importer. |
||
108 | FunctionImporter(const ModuleSummaryIndex &Index, ModuleLoaderTy ModuleLoader, |
||
109 | bool ClearDSOLocalOnDeclarations) |
||
110 | : Index(Index), ModuleLoader(std::move(ModuleLoader)), |
||
111 | ClearDSOLocalOnDeclarations(ClearDSOLocalOnDeclarations) {} |
||
112 | |||
113 | /// Import functions in Module \p M based on the supplied import list. |
||
114 | Expected<bool> importFunctions(Module &M, const ImportMapTy &ImportList); |
||
115 | |||
116 | private: |
||
117 | /// The summaries index used to trigger importing. |
||
118 | const ModuleSummaryIndex &Index; |
||
119 | |||
120 | /// Factory function to load a Module for a given identifier |
||
121 | ModuleLoaderTy ModuleLoader; |
||
122 | |||
123 | /// See the comment of ClearDSOLocalOnDeclarations in |
||
124 | /// Utils/FunctionImportUtils.h. |
||
125 | bool ClearDSOLocalOnDeclarations; |
||
126 | }; |
||
127 | |||
128 | /// The function importing pass |
||
129 | class FunctionImportPass : public PassInfoMixin<FunctionImportPass> { |
||
130 | public: |
||
131 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); |
||
132 | }; |
||
133 | |||
134 | /// Compute all the imports and exports for every module in the Index. |
||
135 | /// |
||
136 | /// \p ModuleToDefinedGVSummaries contains for each Module a map |
||
137 | /// (GUID -> Summary) for every global defined in the module. |
||
138 | /// |
||
139 | /// \p ImportLists will be populated with an entry for every Module we are |
||
140 | /// importing into. This entry is itself a map that can be passed to |
||
141 | /// FunctionImporter::importFunctions() above (see description there). |
||
142 | /// |
||
143 | /// \p ExportLists contains for each Module the set of globals (GUID) that will |
||
144 | /// be imported by another module, or referenced by such a function. I.e. this |
||
145 | /// is the set of globals that need to be promoted/renamed appropriately. |
||
146 | void ComputeCrossModuleImport( |
||
147 | const ModuleSummaryIndex &Index, |
||
148 | const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, |
||
149 | StringMap<FunctionImporter::ImportMapTy> &ImportLists, |
||
150 | StringMap<FunctionImporter::ExportSetTy> &ExportLists); |
||
151 | |||
152 | /// Compute all the imports for the given module using the Index. |
||
153 | /// |
||
154 | /// \p ImportList will be populated with a map that can be passed to |
||
155 | /// FunctionImporter::importFunctions() above (see description there). |
||
156 | void ComputeCrossModuleImportForModule( |
||
157 | StringRef ModulePath, const ModuleSummaryIndex &Index, |
||
158 | FunctionImporter::ImportMapTy &ImportList); |
||
159 | |||
160 | /// Mark all external summaries in \p Index for import into the given module. |
||
161 | /// Used for distributed builds using a distributed index. |
||
162 | /// |
||
163 | /// \p ImportList will be populated with a map that can be passed to |
||
164 | /// FunctionImporter::importFunctions() above (see description there). |
||
165 | void ComputeCrossModuleImportForModuleFromIndex( |
||
166 | StringRef ModulePath, const ModuleSummaryIndex &Index, |
||
167 | FunctionImporter::ImportMapTy &ImportList); |
||
168 | |||
169 | /// PrevailingType enum used as a return type of callback passed |
||
170 | /// to computeDeadSymbolsAndUpdateIndirectCalls. Yes and No values used when |
||
171 | /// status explicitly set by symbols resolution, otherwise status is Unknown. |
||
172 | enum class PrevailingType { Yes, No, Unknown }; |
||
173 | |||
174 | /// Update call edges for indirect calls to local functions added from |
||
175 | /// SamplePGO when needed. Normally this is done during |
||
176 | /// computeDeadSymbolsAndUpdateIndirectCalls, but can be called standalone |
||
177 | /// when that is not called (e.g. during testing). |
||
178 | void updateIndirectCalls(ModuleSummaryIndex &Index); |
||
179 | |||
180 | /// Compute all the symbols that are "dead": i.e these that can't be reached |
||
181 | /// in the graph from any of the given symbols listed in |
||
182 | /// \p GUIDPreservedSymbols. Non-prevailing symbols are symbols without a |
||
183 | /// prevailing copy anywhere in IR and are normally dead, \p isPrevailing |
||
184 | /// predicate returns status of symbol. |
||
185 | /// Also update call edges for indirect calls to local functions added from |
||
186 | /// SamplePGO when needed. |
||
187 | void computeDeadSymbolsAndUpdateIndirectCalls( |
||
188 | ModuleSummaryIndex &Index, |
||
189 | const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols, |
||
190 | function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing); |
||
191 | |||
192 | /// Compute dead symbols and run constant propagation in combined index |
||
193 | /// after that. |
||
194 | void computeDeadSymbolsWithConstProp( |
||
195 | ModuleSummaryIndex &Index, |
||
196 | const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols, |
||
197 | function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing, |
||
198 | bool ImportEnabled); |
||
199 | |||
200 | /// Converts value \p GV to declaration, or replaces with a declaration if |
||
201 | /// it is an alias. Returns true if converted, false if replaced. |
||
202 | bool convertToDeclaration(GlobalValue &GV); |
||
203 | |||
204 | /// Compute the set of summaries needed for a ThinLTO backend compilation of |
||
205 | /// \p ModulePath. |
||
206 | // |
||
207 | /// This includes summaries from that module (in case any global summary based |
||
208 | /// optimizations were recorded) and from any definitions in other modules that |
||
209 | /// should be imported. |
||
210 | // |
||
211 | /// \p ModuleToSummariesForIndex will be populated with the needed summaries |
||
212 | /// from each required module path. Use a std::map instead of StringMap to get |
||
213 | /// stable order for bitcode emission. |
||
214 | void gatherImportedSummariesForModule( |
||
215 | StringRef ModulePath, |
||
216 | const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, |
||
217 | const FunctionImporter::ImportMapTy &ImportList, |
||
218 | std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); |
||
219 | |||
220 | /// Emit into \p OutputFilename the files module \p ModulePath will import from. |
||
221 | std::error_code EmitImportsFiles( |
||
222 | StringRef ModulePath, StringRef OutputFilename, |
||
223 | const std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); |
||
224 | |||
225 | /// Based on the information recorded in the summaries during global |
||
226 | /// summary-based analysis: |
||
227 | /// 1. Resolve prevailing symbol linkages and constrain visibility (CanAutoHide |
||
228 | /// and consider visibility from other definitions for ELF) in \p TheModule |
||
229 | /// 2. (optional) Apply propagated function attributes to \p TheModule if |
||
230 | /// PropagateAttrs is true |
||
231 | void thinLTOFinalizeInModule(Module &TheModule, |
||
232 | const GVSummaryMapTy &DefinedGlobals, |
||
233 | bool PropagateAttrs); |
||
234 | |||
235 | /// Internalize \p TheModule based on the information recorded in the summaries |
||
236 | /// during global summary-based analysis. |
||
237 | void thinLTOInternalizeModule(Module &TheModule, |
||
238 | const GVSummaryMapTy &DefinedGlobals); |
||
239 | |||
240 | } // end namespace llvm |
||
241 | |||
242 | #endif // LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H |