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