llvm.org GIT mirror llvm / e3c0e7f
[ThinLTO] Use bulk importing in llvm-link Summary: Use bulk importing so we can avoid the use of post-pass metadata linking. Cloned the ModuleLazyLoaderCache from the FunctionImport pass to facilitate this. Reviewers: joker.eph Subscribers: dexonsmith, llvm-commits, joker.eph Differential Revision: http://reviews.llvm.org/D18455 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264326 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
1 changed file(s) with 95 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
110110 if (Verbose) errs() << "Loading '" << FN << "'\n";
111111 std::unique_ptr Result =
112112 getLazyIRFileModule(FN, Err, Context, !MaterializeMetadata);
113 if (!Result)
113 if (!Result) {
114114 Err.print(argv0, errs());
115 return nullptr;
116 }
115117
116118 if (MaterializeMetadata) {
117119 Result->materializeMetadata();
120122
121123 return Result;
122124 }
125
126 namespace {
127
128 /// Helper to load on demand a Module from file and cache it for subsequent
129 /// queries during function importing.
130 class ModuleLazyLoaderCache {
131 /// Cache of lazily loaded module for import.
132 StringMap> ModuleMap;
133
134 /// Retrieve a Module from the cache or lazily load it on demand.
135 std::function(const char *argv0,
136 const std::string &FileName)>
137 createLazyModule;
138
139 public:
140 /// Create the loader, Module will be initialized in \p Context.
141 ModuleLazyLoaderCache(std::function(
142 const char *argv0, const std::string &FileName)>
143 createLazyModule)
144 : createLazyModule(createLazyModule) {}
145
146 /// Retrieve a Module from the cache or lazily load it on demand.
147 Module &operator()(const char *argv0, const std::string &FileName);
148
149 std::unique_ptr takeModule(const std::string &FileName) {
150 auto I = ModuleMap.find(FileName);
151 assert(I != ModuleMap.end());
152 std::unique_ptr Ret = std::move(I->second);
153 ModuleMap.erase(I);
154 return Ret;
155 }
156 };
157
158 // Get a Module for \p FileName from the cache, or load it lazily.
159 Module &ModuleLazyLoaderCache::operator()(const char *argv0,
160 const std::string &Identifier) {
161 auto &Module = ModuleMap[Identifier];
162 if (!Module)
163 Module = createLazyModule(argv0, Identifier);
164 return *Module;
165 }
166 } // anonymous namespace
123167
124168 static void diagnosticHandler(const DiagnosticInfo &DI) {
125169 unsigned Severity = DI.getSeverity();
149193 /// Import any functions requested via the -import option.
150194 static bool importFunctions(const char *argv0, LLVMContext &Context,
151195 Linker &L) {
152 StringMap>>
153 ModuleToTempMDValsMap;
196 if (SummaryIndex.empty())
197 return true;
198 ErrorOr> IndexOrErr =
199 llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
200 std::error_code EC = IndexOrErr.getError();
201 if (EC) {
202 errs() << EC.message() << '\n';
203 return false;
204 }
205 auto Index = std::move(IndexOrErr.get());
206
207 // Map of Module -> List of globals to import from the Module
208 std::map> ModuleToGlobalsToImportMap;
209 auto ModuleLoader = [&Context](const char *argv0,
210 const std::string &Identifier) {
211 return loadFile(argv0, Identifier, Context, false);
212 };
213 ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader);
154214 for (const auto &Import : Imports) {
155215 // Identify the requested function and its bitcode source file.
156216 size_t Idx = Import.find(':');
162222 std::string FileName = Import.substr(Idx + 1, std::string::npos);
163223
164224 // Load the specified source module.
165 std::unique_ptr M = loadFile(argv0, FileName, Context, false);
166 if (!M.get()) {
167 errs() << argv0 << ": error loading file '" << FileName << "'\n";
168 return false;
169 }
170
171 if (verifyModule(*M, &errs())) {
225 auto &SrcModule = ModuleLoaderCache(argv0, FileName);
226
227 if (verifyModule(SrcModule, &errs())) {
172228 errs() << argv0 << ": " << FileName
173229 << ": error: input module is broken!\n";
174230 return false;
175231 }
176232
177 Function *F = M->getFunction(FunctionName);
233 Function *F = SrcModule.getFunction(FunctionName);
178234 if (!F) {
179235 errs() << "Ignoring import request for non-existent function "
180236 << FunctionName << " from " << FileName << "\n";
192248 if (Verbose)
193249 errs() << "Importing " << FunctionName << " from " << FileName << "\n";
194250
195 // Link in the specified function.
196 DenseSet GlobalsToImport;
197 GlobalsToImport.insert(F);
198
199 if (!SummaryIndex.empty()) {
200 ErrorOr> IndexOrErr =
201 llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
202 std::error_code EC = IndexOrErr.getError();
203 if (EC) {
204 errs() << EC.message() << '\n';
205 return false;
206 }
207 auto Index = std::move(IndexOrErr.get());
208
209 // Linkage Promotion and renaming
210 if (renameModuleForThinLTO(*M, *Index, &GlobalsToImport))
211 return true;
212 }
213
214 // Save the mapping of value ids to temporary metadata created when
215 // importing this function. If we have already imported from this module,
216 // add new temporary metadata to the existing mapping.
217 auto &TempMDVals = ModuleToTempMDValsMap[FileName];
218 if (!TempMDVals)
219 TempMDVals = llvm::make_unique>();
220
221 if (L.linkInModule(std::move(M), Linker::Flags::None, &GlobalsToImport,
222 TempMDVals.get()))
223 return false;
224 }
225
226 // Now link in metadata for all modules from which we imported functions.
227 for (StringMapEntry>> &SME :
228 ModuleToTempMDValsMap) {
229 // Load the specified source module.
230 std::unique_ptr M = loadFile(argv0, SME.getKey(), Context, true);
231 if (!M.get()) {
232 errs() << argv0 << ": error loading file '" << SME.getKey() << "'\n";
233 return false;
234 }
235
236 if (verifyModule(*M, &errs())) {
237 errs() << argv0 << ": " << SME.getKey()
238 << ": error: input module is broken!\n";
239 return false;
240 }
241
242 // Link in all necessary metadata from this module.
243 if (L.linkInMetadata(std::move(M), SME.getValue().get()))
244 return false;
245 }
251 auto &Entry = ModuleToGlobalsToImportMap[SrcModule.getModuleIdentifier()];
252 Entry.insert(F);
253
254 F->materialize();
255 }
256
257 // Do the actual import of globals now, one Module at a time
258 for (auto &GlobalsToImportPerModule : ModuleToGlobalsToImportMap) {
259 // Get the module for the import
260 auto &GlobalsToImport = GlobalsToImportPerModule.second;
261 std::unique_ptr SrcModule =
262 ModuleLoaderCache.takeModule(GlobalsToImportPerModule.first);
263 assert(&Context == &SrcModule->getContext() && "Context mismatch");
264
265 // If modules were created with lazy metadata loading, materialize it
266 // now, before linking it (otherwise this will be a noop).
267 SrcModule->materializeMetadata();
268 UpgradeDebugInfo(*SrcModule);
269
270 // Linkage Promotion and renaming
271 if (renameModuleForThinLTO(*SrcModule, *Index, &GlobalsToImport))
272 return true;
273
274 if (L.linkInModule(std::move(SrcModule), Linker::Flags::None,
275 &GlobalsToImport))
276 return false;
277 }
278
246279 return true;
247280 }
248281