Line data Source code
1 : //===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
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 the "backend" phase of LTO, i.e. it performs
11 : // optimization and code generation on a loaded module. It is generally used
12 : // internally by the LTO class but can also be used independently, for example
13 : // to implement a standalone ThinLTO backend.
14 : //
15 : //===----------------------------------------------------------------------===//
16 :
17 : #include "llvm/LTO/LTOBackend.h"
18 : #include "llvm/Analysis/AliasAnalysis.h"
19 : #include "llvm/Analysis/CGSCCPassManager.h"
20 : #include "llvm/Analysis/TargetLibraryInfo.h"
21 : #include "llvm/Analysis/TargetTransformInfo.h"
22 : #include "llvm/Bitcode/BitcodeReader.h"
23 : #include "llvm/Bitcode/BitcodeWriter.h"
24 : #include "llvm/IR/LegacyPassManager.h"
25 : #include "llvm/IR/PassManager.h"
26 : #include "llvm/IR/Verifier.h"
27 : #include "llvm/LTO/LTO.h"
28 : #include "llvm/MC/SubtargetFeature.h"
29 : #include "llvm/Object/ModuleSymbolTable.h"
30 : #include "llvm/Passes/PassBuilder.h"
31 : #include "llvm/Support/Error.h"
32 : #include "llvm/Support/FileSystem.h"
33 : #include "llvm/Support/MemoryBuffer.h"
34 : #include "llvm/Support/Path.h"
35 : #include "llvm/Support/Program.h"
36 : #include "llvm/Support/raw_ostream.h"
37 : #include "llvm/Support/TargetRegistry.h"
38 : #include "llvm/Support/ThreadPool.h"
39 : #include "llvm/Target/TargetMachine.h"
40 : #include "llvm/Transforms/IPO.h"
41 : #include "llvm/Transforms/IPO/PassManagerBuilder.h"
42 : #include "llvm/Transforms/Scalar/LoopPassManager.h"
43 : #include "llvm/Transforms/Utils/FunctionImportUtils.h"
44 : #include "llvm/Transforms/Utils/SplitModule.h"
45 :
46 : using namespace llvm;
47 : using namespace lto;
48 :
49 0 : LLVM_ATTRIBUTE_NORETURN static void reportOpenError(StringRef Path, Twine Msg) {
50 0 : errs() << "failed to open " << Path << ": " << Msg << '\n';
51 0 : errs().flush();
52 0 : exit(1);
53 : }
54 :
55 173 : Error Config::addSaveTemps(std::string OutputFileName,
56 : bool UseInputModulePath) {
57 173 : ShouldDiscardValueNames = false;
58 :
59 : std::error_code EC;
60 346 : ResolutionFile = llvm::make_unique<raw_fd_ostream>(
61 173 : OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::F_Text);
62 173 : if (EC)
63 0 : return errorCodeToError(EC);
64 :
65 : auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
66 : // Keep track of the hook provided by the linker, which also needs to run.
67 : ModuleHookFn LinkerHook = Hook;
68 : Hook = [=](unsigned Task, const Module &M) {
69 : // If the linker's hook returned false, we need to pass that result
70 : // through.
71 : if (LinkerHook && !LinkerHook(Task, M))
72 : return false;
73 :
74 : std::string PathPrefix;
75 : // If this is the combined module (not a ThinLTO backend compile) or the
76 : // user hasn't requested using the input module's path, emit to a file
77 : // named from the provided OutputFileName with the Task ID appended.
78 : if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
79 : PathPrefix = OutputFileName;
80 : if (Task != (unsigned)-1)
81 : PathPrefix += utostr(Task) + ".";
82 : } else
83 : PathPrefix = M.getModuleIdentifier() + ".";
84 : std::string Path = PathPrefix + PathSuffix + ".bc";
85 : std::error_code EC;
86 : raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
87 : // Because -save-temps is a debugging feature, we report the error
88 : // directly and exit.
89 : if (EC)
90 : reportOpenError(Path, EC.message());
91 : WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false);
92 : return true;
93 : };
94 173 : };
95 :
96 173 : setHook("0.preopt", PreOptModuleHook);
97 173 : setHook("1.promote", PostPromoteModuleHook);
98 173 : setHook("2.internalize", PostInternalizeModuleHook);
99 173 : setHook("3.import", PostImportModuleHook);
100 173 : setHook("4.opt", PostOptModuleHook);
101 346 : setHook("5.precodegen", PreCodeGenModuleHook);
102 :
103 0 : CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
104 : std::string Path = OutputFileName + "index.bc";
105 : std::error_code EC;
106 : raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
107 : // Because -save-temps is a debugging feature, we report the error
108 : // directly and exit.
109 : if (EC)
110 : reportOpenError(Path, EC.message());
111 : WriteIndexToFile(Index, OS);
112 :
113 : Path = OutputFileName + "index.dot";
114 : raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::F_None);
115 : if (EC)
116 : reportOpenError(Path, EC.message());
117 : Index.exportToDot(OSDot);
118 : return true;
119 346 : };
120 :
121 : return Error::success();
122 : }
123 :
124 : namespace {
125 :
126 : std::unique_ptr<TargetMachine>
127 708 : createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
128 : StringRef TheTriple = M.getTargetTriple();
129 708 : SubtargetFeatures Features;
130 1416 : Features.getDefaultSubtargetFeatures(Triple(TheTriple));
131 829 : for (const std::string &A : Conf.MAttrs)
132 121 : Features.AddFeature(A);
133 :
134 : Reloc::Model RelocModel;
135 708 : if (Conf.RelocModel)
136 698 : RelocModel = *Conf.RelocModel;
137 : else
138 : RelocModel =
139 10 : M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
140 :
141 : Optional<CodeModel::Model> CodeModel;
142 708 : if (Conf.CodeModel)
143 4 : CodeModel = *Conf.CodeModel;
144 : else
145 1408 : CodeModel = M.getCodeModel();
146 :
147 : return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
148 708 : TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
149 1435 : CodeModel, Conf.CGOptLevel));
150 : }
151 :
152 23 : static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
153 : unsigned OptLevel, bool IsThinLTO,
154 : ModuleSummaryIndex *ExportSummary,
155 : const ModuleSummaryIndex *ImportSummary) {
156 : Optional<PGOOptions> PGOOpt;
157 23 : if (!Conf.SampleProfile.empty())
158 6 : PGOOpt = PGOOptions("", "", Conf.SampleProfile, Conf.ProfileRemapping,
159 : false, true);
160 :
161 69 : PassBuilder PB(TM, PGOOpt);
162 : AAManager AA;
163 :
164 : // Parse a custom AA pipeline if asked to.
165 23 : if (auto Err = PB.parseAAPipeline(AA, "default"))
166 0 : report_fatal_error("Error parsing default AA pipeline");
167 :
168 46 : LoopAnalysisManager LAM(Conf.DebugPassManager);
169 46 : FunctionAnalysisManager FAM(Conf.DebugPassManager);
170 46 : CGSCCAnalysisManager CGAM(Conf.DebugPassManager);
171 46 : ModuleAnalysisManager MAM(Conf.DebugPassManager);
172 :
173 : // Register the AA manager first so that our version is the one used.
174 23 : FAM.registerPass([&] { return std::move(AA); });
175 :
176 : // Register all the basic analyses with the managers.
177 23 : PB.registerModuleAnalyses(MAM);
178 23 : PB.registerCGSCCAnalyses(CGAM);
179 23 : PB.registerFunctionAnalyses(FAM);
180 23 : PB.registerLoopAnalyses(LAM);
181 23 : PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
182 :
183 23 : ModulePassManager MPM(Conf.DebugPassManager);
184 : // FIXME (davide): verify the input.
185 :
186 : PassBuilder::OptimizationLevel OL;
187 :
188 : switch (OptLevel) {
189 0 : default:
190 0 : llvm_unreachable("Invalid optimization level");
191 : case 0:
192 : OL = PassBuilder::O0;
193 : break;
194 : case 1:
195 : OL = PassBuilder::O1;
196 : break;
197 : case 2:
198 : OL = PassBuilder::O2;
199 : break;
200 : case 3:
201 : OL = PassBuilder::O3;
202 : break;
203 : }
204 :
205 23 : if (IsThinLTO)
206 22 : MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager,
207 : ImportSummary);
208 : else
209 24 : MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager, ExportSummary);
210 23 : MPM.run(Mod, MAM);
211 :
212 : // FIXME (davide): verify the output.
213 23 : }
214 :
215 9 : static void runNewPMCustomPasses(Module &Mod, TargetMachine *TM,
216 : std::string PipelineDesc,
217 : std::string AAPipelineDesc,
218 : bool DisableVerify) {
219 23 : PassBuilder PB(TM);
220 : AAManager AA;
221 :
222 : // Parse a custom AA pipeline if asked to.
223 9 : if (!AAPipelineDesc.empty())
224 6 : if (auto Err = PB.parseAAPipeline(AA, AAPipelineDesc))
225 4 : report_fatal_error("unable to parse AA pipeline description '" +
226 4 : AAPipelineDesc + "': " + toString(std::move(Err)));
227 :
228 12 : LoopAnalysisManager LAM;
229 12 : FunctionAnalysisManager FAM;
230 12 : CGSCCAnalysisManager CGAM;
231 12 : ModuleAnalysisManager MAM;
232 :
233 : // Register the AA manager first so that our version is the one used.
234 7 : FAM.registerPass([&] { return std::move(AA); });
235 :
236 : // Register all the basic analyses with the managers.
237 7 : PB.registerModuleAnalyses(MAM);
238 7 : PB.registerCGSCCAnalyses(CGAM);
239 7 : PB.registerFunctionAnalyses(FAM);
240 7 : PB.registerLoopAnalyses(LAM);
241 7 : PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
242 :
243 : ModulePassManager MPM;
244 :
245 : // Always verify the input.
246 7 : MPM.addPass(VerifierPass());
247 :
248 : // Now, add all the passes we've been requested to.
249 9 : if (auto Err = PB.parsePassPipeline(MPM, PipelineDesc))
250 4 : report_fatal_error("unable to parse pass pipeline description '" +
251 4 : PipelineDesc + "': " + toString(std::move(Err)));
252 :
253 5 : if (!DisableVerify)
254 5 : MPM.addPass(VerifierPass());
255 5 : MPM.run(Mod, MAM);
256 5 : }
257 :
258 666 : static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
259 : bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
260 : const ModuleSummaryIndex *ImportSummary) {
261 1332 : legacy::PassManager passes;
262 666 : passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
263 :
264 1332 : PassManagerBuilder PMB;
265 666 : PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
266 666 : PMB.Inliner = createFunctionInliningPass();
267 666 : PMB.ExportSummary = ExportSummary;
268 666 : PMB.ImportSummary = ImportSummary;
269 : // Unconditionally verify input since it is not verified before this
270 : // point and has unknown origin.
271 666 : PMB.VerifyInput = true;
272 666 : PMB.VerifyOutput = !Conf.DisableVerify;
273 666 : PMB.LoopVectorize = true;
274 666 : PMB.SLPVectorize = true;
275 666 : PMB.OptLevel = Conf.OptLevel;
276 666 : PMB.PGOSampleUse = Conf.SampleProfile;
277 666 : if (IsThinLTO)
278 238 : PMB.populateThinLTOPassManager(passes);
279 : else
280 428 : PMB.populateLTOPassManager(passes);
281 666 : passes.run(Mod);
282 666 : }
283 :
284 698 : bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
285 : bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
286 : const ModuleSummaryIndex *ImportSummary) {
287 : // FIXME: Plumb the combined index into the new pass manager.
288 698 : if (!Conf.OptPipeline.empty())
289 14 : runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
290 9 : Conf.DisableVerify);
291 689 : else if (Conf.UseNewPM)
292 23 : runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
293 : ImportSummary);
294 : else
295 666 : runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
296 978 : return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
297 : }
298 :
299 699 : void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
300 : unsigned Task, Module &Mod) {
301 992 : if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
302 5 : return;
303 :
304 : std::unique_ptr<ToolOutputFile> DwoOut;
305 : SmallString<1024> DwoFile(Conf.DwoPath);
306 694 : if (!Conf.DwoDir.empty()) {
307 : std::error_code EC;
308 8 : if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
309 0 : report_fatal_error("Failed to create directory " + Conf.DwoDir + ": " +
310 : EC.message());
311 :
312 : DwoFile = Conf.DwoDir;
313 4 : sys::path::append(DwoFile, std::to_string(Task) + ".dwo");
314 : }
315 :
316 694 : if (!DwoFile.empty()) {
317 : std::error_code EC;
318 5 : TM->Options.MCOptions.SplitDwarfFile = DwoFile.str().str();
319 5 : DwoOut = llvm::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::F_None);
320 5 : if (EC)
321 0 : report_fatal_error("Failed to open " + DwoFile + ": " + EC.message());
322 : }
323 :
324 693 : auto Stream = AddStream(Task);
325 1386 : legacy::PassManager CodeGenPasses;
326 693 : if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
327 : DwoOut ? &DwoOut->os() : nullptr,
328 693 : Conf.CGFileType))
329 0 : report_fatal_error("Failed to setup codegen");
330 693 : CodeGenPasses.run(Mod);
331 :
332 693 : if (DwoOut)
333 : DwoOut->keep();
334 : }
335 :
336 5 : void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
337 : unsigned ParallelCodeGenParallelismLevel,
338 : std::unique_ptr<Module> Mod) {
339 10 : ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
340 5 : unsigned ThreadCount = 0;
341 5 : const Target *T = &TM->getTarget();
342 :
343 10 : SplitModule(
344 : std::move(Mod), ParallelCodeGenParallelismLevel,
345 : [&](std::unique_ptr<Module> MPart) {
346 : // We want to clone the module in a new context to multi-thread the
347 : // codegen. We do it by serializing partition modules to bitcode
348 : // (while still on the main thread, in order to avoid data races) and
349 : // spinning up new threads which deserialize the partitions into
350 : // separate contexts.
351 : // FIXME: Provide a more direct way to do this in LLVM.
352 : SmallString<0> BC;
353 : raw_svector_ostream BCOS(BC);
354 : WriteBitcodeToFile(*MPart, BCOS);
355 :
356 : // Enqueue the task
357 : CodegenThreadPool.async(
358 : [&](const SmallString<0> &BC, unsigned ThreadId) {
359 : LTOLLVMContext Ctx(C);
360 : Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
361 : MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
362 : Ctx);
363 : if (!MOrErr)
364 : report_fatal_error("Failed to read bitcode");
365 : std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
366 :
367 : std::unique_ptr<TargetMachine> TM =
368 : createTargetMachine(C, T, *MPartInCtx);
369 :
370 : codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
371 : },
372 : // Pass BC using std::move to ensure that it get moved rather than
373 : // copied into the thread's context.
374 : std::move(BC), ThreadCount++);
375 : },
376 : false);
377 :
378 : // Because the inner lambda (which runs in a worker thread) captures our local
379 : // variables, we need to wait for the worker threads to terminate before we
380 : // can leave the function scope.
381 5 : CodegenThreadPool.wait();
382 5 : }
383 :
384 698 : Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
385 698 : if (!C.OverrideTriple.empty())
386 2 : Mod.setTargetTriple(C.OverrideTriple);
387 696 : else if (Mod.getTargetTriple().empty())
388 2 : Mod.setTargetTriple(C.DefaultTriple);
389 :
390 : std::string Msg;
391 698 : const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
392 698 : if (!T)
393 0 : return make_error<StringError>(Msg, inconvertibleErrorCode());
394 : return T;
395 : }
396 :
397 : }
398 :
399 : static Error
400 693 : finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile) {
401 : // Make sure we flush the diagnostic remarks file in case the linker doesn't
402 : // call the global destructors before exiting.
403 693 : if (!DiagOutputFile)
404 : return Error::success();
405 : DiagOutputFile->keep();
406 9 : DiagOutputFile->os().flush();
407 : return Error::success();
408 : }
409 :
410 448 : Error lto::backend(Config &C, AddStreamFn AddStream,
411 : unsigned ParallelCodeGenParallelismLevel,
412 : std::unique_ptr<Module> Mod,
413 : ModuleSummaryIndex &CombinedIndex) {
414 448 : Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
415 448 : if (!TOrErr)
416 : return TOrErr.takeError();
417 :
418 448 : std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
419 :
420 : // Setup optimization remarks.
421 : auto DiagFileOrErr = lto::setupOptimizationRemarks(
422 1339 : Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness);
423 448 : if (!DiagFileOrErr)
424 : return DiagFileOrErr.takeError();
425 : auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
426 :
427 448 : if (!C.CodeGenOnly) {
428 448 : if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
429 : /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
430 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
431 : }
432 :
433 444 : if (ParallelCodeGenParallelismLevel == 1) {
434 877 : codegen(C, TM.get(), AddStream, 0, *Mod);
435 : } else {
436 10 : splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
437 : std::move(Mod));
438 : }
439 886 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
440 : }
441 :
442 250 : static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
443 : const ModuleSummaryIndex &Index) {
444 : std::vector<GlobalValue*> DeadGVs;
445 1099 : for (auto &GV : Mod.global_values())
446 1198 : if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
447 372 : if (!Index.isGlobalValueLive(GVS)) {
448 36 : DeadGVs.push_back(&GV);
449 36 : convertToDeclaration(GV);
450 : }
451 :
452 : // Now that all dead bodies have been dropped, delete the actual objects
453 : // themselves when possible.
454 286 : for (GlobalValue *GV : DeadGVs) {
455 36 : GV->removeDeadConstantUsers();
456 : // Might reference something defined in native object (i.e. dropped a
457 : // non-prevailing IR def, but we need to keep the declaration).
458 36 : if (GV->use_empty())
459 31 : GV->eraseFromParent();
460 : }
461 250 : }
462 :
463 250 : Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
464 : Module &Mod, const ModuleSummaryIndex &CombinedIndex,
465 : const FunctionImporter::ImportMapTy &ImportList,
466 : const GVSummaryMapTy &DefinedGlobals,
467 : MapVector<StringRef, BitcodeModule> &ModuleMap) {
468 250 : Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
469 250 : if (!TOrErr)
470 : return TOrErr.takeError();
471 :
472 250 : std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
473 :
474 : // Setup optimization remarks.
475 : auto DiagFileOrErr = lto::setupOptimizationRemarks(
476 750 : Mod.getContext(), Conf.RemarksFilename, Conf.RemarksWithHotness, Task);
477 250 : if (!DiagFileOrErr)
478 : return DiagFileOrErr.takeError();
479 : auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
480 :
481 250 : if (Conf.CodeGenOnly) {
482 0 : codegen(Conf, TM.get(), AddStream, Task, Mod);
483 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
484 : }
485 :
486 365 : if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
487 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
488 :
489 250 : renameModuleForThinLTO(Mod, CombinedIndex);
490 :
491 250 : dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex);
492 :
493 250 : thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);
494 :
495 365 : if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
496 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
497 :
498 250 : if (!DefinedGlobals.empty())
499 240 : thinLTOInternalizeModule(Mod, DefinedGlobals);
500 :
501 250 : if (Conf.PostInternalizeModuleHook &&
502 115 : !Conf.PostInternalizeModuleHook(Task, Mod))
503 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
504 :
505 : auto ModuleLoader = [&](StringRef Identifier) {
506 : assert(Mod.getContext().isODRUniquingDebugTypes() &&
507 : "ODR Type uniquing should be enabled on the context");
508 : auto I = ModuleMap.find(Identifier);
509 : assert(I != ModuleMap.end());
510 : return I->second.getLazyModule(Mod.getContext(),
511 : /*ShouldLazyLoadMetadata=*/true,
512 : /*IsImporting*/ true);
513 : };
514 :
515 250 : FunctionImporter Importer(CombinedIndex, ModuleLoader);
516 500 : if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
517 : return Err;
518 :
519 365 : if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
520 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
521 :
522 250 : if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
523 : /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
524 0 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
525 :
526 500 : codegen(Conf, TM.get(), AddStream, Task, Mod);
527 500 : return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
528 : }
|