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 |