LCOV - code coverage report
Current view: top level - lib/LTO - LTOBackend.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 197 217 90.8 %
Date: 2018-02-19 03:08:00 Functions: 21 23 91.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13