LCOV - code coverage report
Current view: top level - lib/LTO - LTOBackend.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 206 235 87.7 %
Date: 2017-09-14 15:23:50 Functions: 20 22 90.9 %
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         131 : Error Config::addSaveTemps(std::string OutputFileName,
      52             :                            bool UseInputModulePath) {
      53         131 :   ShouldDiscardValueNames = false;
      54             : 
      55         131 :   std::error_code EC;
      56         393 :   ResolutionFile = llvm::make_unique<raw_fd_ostream>(
      57         393 :       OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::F_Text);
      58         131 :   if (EC)
      59           0 :     return errorCodeToError(EC);
      60             : 
      61         786 :   auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
      62             :     // Keep track of the hook provided by the linker, which also needs to run.
      63        1572 :     ModuleHookFn LinkerHook = Hook;
      64       17309 :     Hook = [=](unsigned Task, const Module &M) {
      65             :       // If the linker's hook returned false, we need to pass that result
      66             :       // through.
      67        1606 :       if (LinkerHook && !LinkerHook(Task, M))
      68             :         return false;
      69             : 
      70         803 :       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        2392 :       if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
      75        2563 :         PathPrefix = OutputFileName + utostr(Task);
      76             :       } else
      77         210 :         PathPrefix = M.getModuleIdentifier();
      78        3211 :       std::string Path = PathPrefix + "." + PathSuffix + ".bc";
      79         803 :       std::error_code EC;
      80        1606 :       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         803 :       if (EC)
      84           0 :         reportOpenError(Path, EC.message());
      85         803 :       WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
      86             :       return true;
      87        3930 :     };
      88         917 :   };
      89             : 
      90         393 :   setHook("0.preopt", PreOptModuleHook);
      91         393 :   setHook("1.promote", PostPromoteModuleHook);
      92         393 :   setHook("2.internalize", PostInternalizeModuleHook);
      93         393 :   setHook("3.import", PostImportModuleHook);
      94         393 :   setHook("4.opt", PostOptModuleHook);
      95         524 :   setHook("5.precodegen", PreCodeGenModuleHook);
      96             : 
      97        1354 :   CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
      98          88 :     std::string Path = OutputFileName + "index.bc";
      99          44 :     std::error_code EC;
     100          88 :     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          44 :     if (EC)
     104           0 :       reportOpenError(Path, EC.message());
     105          44 :     WriteIndexToFile(Index, OS);
     106          44 :     return true;
     107         262 :   };
     108             : 
     109         393 :   return Error::success();
     110             : }
     111             : 
     112             : namespace {
     113             : 
     114             : std::unique_ptr<TargetMachine>
     115         389 : createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
     116         778 :   StringRef TheTriple = M.getTargetTriple();
     117         778 :   SubtargetFeatures Features;
     118         778 :   Features.getDefaultSubtargetFeatures(Triple(TheTriple));
     119        1587 :   for (const std::string &A : Conf.MAttrs)
     120          31 :     Features.AddFeature(A);
     121             : 
     122             :   Reloc::Model RelocModel;
     123         389 :   if (Conf.RelocModel)
     124         758 :     RelocModel = *Conf.RelocModel;
     125             :   else
     126             :     RelocModel =
     127          10 :         M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
     128             : 
     129             :   return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
     130         778 :       TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
     131        3501 :       Conf.CodeModel, Conf.CGOptLevel));
     132             : }
     133             : 
     134           4 : static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
     135             :                            unsigned OptLevel, bool IsThinLTO) {
     136           8 :   Optional<PGOOptions> PGOOpt;
     137           8 :   if (!Conf.SampleProfile.empty())
     138           9 :     PGOOpt = PGOOptions("", "", Conf.SampleProfile, false, true);
     139             : 
     140          12 :   PassBuilder PB(TM, PGOOpt);
     141           8 :   AAManager AA;
     142             : 
     143             :   // Parse a custom AA pipeline if asked to.
     144           4 :   if (!PB.parseAAPipeline(AA, "default"))
     145           0 :     report_fatal_error("Error parsing default AA pipeline");
     146             : 
     147           8 :   LoopAnalysisManager LAM(Conf.DebugPassManager);
     148           8 :   FunctionAnalysisManager FAM(Conf.DebugPassManager);
     149           8 :   CGSCCAnalysisManager CGAM(Conf.DebugPassManager);
     150           8 :   ModuleAnalysisManager MAM(Conf.DebugPassManager);
     151             : 
     152             :   // Register the AA manager first so that our version is the one used.
     153          12 :   FAM.registerPass([&] { return std::move(AA); });
     154             : 
     155             :   // Register all the basic analyses with the managers.
     156           4 :   PB.registerModuleAnalyses(MAM);
     157           4 :   PB.registerCGSCCAnalyses(CGAM);
     158           4 :   PB.registerFunctionAnalyses(FAM);
     159           4 :   PB.registerLoopAnalyses(LAM);
     160           4 :   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
     161             : 
     162          12 :   ModulePassManager MPM(Conf.DebugPassManager);
     163             :   // FIXME (davide): verify the input.
     164             : 
     165             :   PassBuilder::OptimizationLevel OL;
     166             : 
     167           4 :   switch (OptLevel) {
     168           0 :   default:
     169           0 :     llvm_unreachable("Invalid optimization level");
     170             :   case 0:
     171             :     OL = PassBuilder::O0;
     172             :     break;
     173           0 :   case 1:
     174           0 :     OL = PassBuilder::O1;
     175           0 :     break;
     176           4 :   case 2:
     177           4 :     OL = PassBuilder::O2;
     178           4 :     break;
     179           0 :   case 3:
     180           0 :     OL = PassBuilder::O3;
     181           0 :     break;
     182             :   }
     183             : 
     184           4 :   if (IsThinLTO)
     185           6 :     MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager);
     186             :   else
     187           6 :     MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager);
     188           4 :   MPM.run(Mod, MAM);
     189             : 
     190             :   // FIXME (davide): verify the output.
     191           4 : }
     192             : 
     193           8 : static void runNewPMCustomPasses(Module &Mod, TargetMachine *TM,
     194             :                                  std::string PipelineDesc,
     195             :                                  std::string AAPipelineDesc,
     196             :                                  bool DisableVerify) {
     197          20 :   PassBuilder PB(TM);
     198          12 :   AAManager AA;
     199             : 
     200             :   // Parse a custom AA pipeline if asked to.
     201           8 :   if (!AAPipelineDesc.empty())
     202           4 :     if (!PB.parseAAPipeline(AA, AAPipelineDesc))
     203           2 :       report_fatal_error("unable to parse AA pipeline description: " +
     204             :                          AAPipelineDesc);
     205             : 
     206          10 :   LoopAnalysisManager LAM;
     207          10 :   FunctionAnalysisManager FAM;
     208          10 :   CGSCCAnalysisManager CGAM;
     209          10 :   ModuleAnalysisManager MAM;
     210             : 
     211             :   // Register the AA manager first so that our version is the one used.
     212          18 :   FAM.registerPass([&] { return std::move(AA); });
     213             : 
     214             :   // Register all the basic analyses with the managers.
     215           6 :   PB.registerModuleAnalyses(MAM);
     216           6 :   PB.registerCGSCCAnalyses(CGAM);
     217           6 :   PB.registerFunctionAnalyses(FAM);
     218           6 :   PB.registerLoopAnalyses(LAM);
     219           6 :   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
     220             : 
     221          10 :   ModulePassManager MPM;
     222             : 
     223             :   // Always verify the input.
     224           6 :   MPM.addPass(VerifierPass());
     225             : 
     226             :   // Now, add all the passes we've been requested to.
     227           6 :   if (!PB.parsePassPipeline(MPM, PipelineDesc))
     228           2 :     report_fatal_error("unable to parse pass pipeline description: " +
     229             :                        PipelineDesc);
     230             : 
     231           4 :   if (!DisableVerify)
     232           4 :     MPM.addPass(VerifierPass());
     233           4 :   MPM.run(Mod, MAM);
     234           4 : }
     235             : 
     236         369 : static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
     237             :                            bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
     238             :                            const ModuleSummaryIndex *ImportSummary) {
     239         738 :   legacy::PassManager passes;
     240         738 :   passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
     241             : 
     242         738 :   PassManagerBuilder PMB;
     243         738 :   PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
     244         369 :   PMB.Inliner = createFunctionInliningPass();
     245         369 :   PMB.ExportSummary = ExportSummary;
     246         369 :   PMB.ImportSummary = ImportSummary;
     247             :   // Unconditionally verify input since it is not verified before this
     248             :   // point and has unknown origin.
     249         369 :   PMB.VerifyInput = true;
     250         369 :   PMB.VerifyOutput = !Conf.DisableVerify;
     251         369 :   PMB.LoopVectorize = true;
     252         369 :   PMB.SLPVectorize = true;
     253         369 :   PMB.OptLevel = Conf.OptLevel;
     254         738 :   PMB.PGOSampleUse = Conf.SampleProfile;
     255         369 :   if (IsThinLTO)
     256         166 :     PMB.populateThinLTOPassManager(passes);
     257             :   else
     258         203 :     PMB.populateLTOPassManager(passes);
     259         369 :   passes.run(Mod);
     260         369 : }
     261             : 
     262         381 : bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
     263             :          bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
     264             :          const ModuleSummaryIndex *ImportSummary) {
     265             :   // FIXME: Plumb the combined index into the new pass manager.
     266         762 :   if (!Conf.OptPipeline.empty())
     267          32 :     runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
     268           8 :                          Conf.DisableVerify);
     269         373 :   else if (Conf.UseNewPM)
     270           4 :     runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO);
     271             :   else
     272         369 :     runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
     273         918 :   return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
     274             : }
     275             : 
     276         381 : void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
     277             :              unsigned Task, Module &Mod) {
     278         932 :   if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
     279           3 :     return;
     280             : 
     281         754 :   auto Stream = AddStream(Task);
     282         754 :   legacy::PassManager CodeGenPasses;
     283        1131 :   if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, Conf.CGFileType))
     284           0 :     report_fatal_error("Failed to setup codegen");
     285         377 :   CodeGenPasses.run(Mod);
     286             : }
     287             : 
     288           4 : void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
     289             :                   unsigned ParallelCodeGenParallelismLevel,
     290             :                   std::unique_ptr<Module> Mod) {
     291           8 :   ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
     292           4 :   unsigned ThreadCount = 0;
     293           4 :   const Target *T = &TM->getTarget();
     294             : 
     295          12 :   SplitModule(
     296           4 :       std::move(Mod), ParallelCodeGenParallelismLevel,
     297           8 :       [&](std::unique_ptr<Module> MPart) {
     298             :         // We want to clone the module in a new context to multi-thread the
     299             :         // codegen. We do it by serializing partition modules to bitcode
     300             :         // (while still on the main thread, in order to avoid data races) and
     301             :         // spinning up new threads which deserialize the partitions into
     302             :         // separate contexts.
     303             :         // FIXME: Provide a more direct way to do this in LLVM.
     304          16 :         SmallString<0> BC;
     305          16 :         raw_svector_ostream BCOS(BC);
     306           8 :         WriteBitcodeToFile(MPart.get(), BCOS);
     307             : 
     308             :         // Enqueue the task
     309          40 :         CodegenThreadPool.async(
     310           8 :             [&](const SmallString<0> &BC, unsigned ThreadId) {
     311          40 :               LTOLLVMContext Ctx(C);
     312             :               Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
     313             :                   MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
     314          40 :                   Ctx);
     315           8 :               if (!MOrErr)
     316           0 :                 report_fatal_error("Failed to read bitcode");
     317          24 :               std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
     318             : 
     319             :               std::unique_ptr<TargetMachine> TM =
     320          32 :                   createTargetMachine(C, T, *MPartInCtx);
     321             : 
     322          48 :               codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
     323           8 :             },
     324             :             // Pass BC using std::move to ensure that it get moved rather than
     325             :             // copied into the thread's context.
     326          16 :             std::move(BC), ThreadCount++);
     327           8 :       },
     328             :       false);
     329             : 
     330             :   // Because the inner lambda (which runs in a worker thread) captures our local
     331             :   // variables, we need to wait for the worker threads to terminate before we
     332             :   // can leave the function scope.
     333           4 :   CodegenThreadPool.wait();
     334           4 : }
     335             : 
     336         380 : Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
     337         760 :   if (!C.OverrideTriple.empty())
     338           2 :     Mod.setTargetTriple(C.OverrideTriple);
     339         379 :   else if (Mod.getTargetTriple().empty())
     340           2 :     Mod.setTargetTriple(C.DefaultTriple);
     341             : 
     342         761 :   std::string Msg;
     343         380 :   const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
     344         381 :   if (!T)
     345           0 :     return make_error<StringError>(Msg, inconvertibleErrorCode());
     346             :   return T;
     347             : }
     348             : 
     349             : }
     350             : 
     351             : static void
     352         207 : finalizeOptimizationRemarks(std::unique_ptr<tool_output_file> DiagOutputFile) {
     353             :   // Make sure we flush the diagnostic remarks file in case the linker doesn't
     354             :   // call the global destructors before exiting.
     355         207 :   if (!DiagOutputFile)
     356             :     return;
     357           8 :   DiagOutputFile->keep();
     358           4 :   DiagOutputFile->os().flush();
     359             : }
     360             : 
     361         212 : Error lto::backend(Config &C, AddStreamFn AddStream,
     362             :                    unsigned ParallelCodeGenParallelismLevel,
     363             :                    std::unique_ptr<Module> Mod,
     364             :                    ModuleSummaryIndex &CombinedIndex) {
     365         419 :   Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
     366         212 :   if (!TOrErr)
     367             :     return TOrErr.takeError();
     368             : 
     369         424 :   std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
     370             : 
     371             :   // Setup optimization remarks.
     372             :   auto DiagFileOrErr = lto::setupOptimizationRemarks(
     373         843 :       Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness);
     374         212 :   if (!DiagFileOrErr)
     375             :     return DiagFileOrErr.takeError();
     376         424 :   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
     377             : 
     378         212 :   if (!C.CodeGenOnly) {
     379         424 :     if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
     380             :              /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) {
     381           0 :       finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
     382           0 :       return Error::success();
     383             :     }
     384             :   }
     385             : 
     386         208 :   if (ParallelCodeGenParallelismLevel == 1) {
     387         815 :     codegen(C, TM.get(), AddStream, 0, *Mod);
     388             :   } else {
     389          12 :     splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
     390           4 :                  std::move(Mod));
     391             :   }
     392         621 :   finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
     393         621 :   return Error::success();
     394             : }
     395             : 
     396         169 : Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
     397             :                        Module &Mod, const ModuleSummaryIndex &CombinedIndex,
     398             :                        const FunctionImporter::ImportMapTy &ImportList,
     399             :                        const GVSummaryMapTy &DefinedGlobals,
     400             :                        MapVector<StringRef, BitcodeModule> &ModuleMap) {
     401         338 :   Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
     402         169 :   if (!TOrErr)
     403             :     return TOrErr.takeError();
     404             : 
     405         169 :   std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
     406             : 
     407         169 :   if (Conf.CodeGenOnly) {
     408           0 :     codegen(Conf, TM.get(), AddStream, Task, Mod);
     409           0 :     return Error::success();
     410             :   }
     411             : 
     412         410 :   if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
     413           0 :     return Error::success();
     414             : 
     415         169 :   renameModuleForThinLTO(Mod, CombinedIndex);
     416             : 
     417         169 :   thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);
     418             : 
     419         410 :   if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
     420           0 :     return Error::success();
     421             : 
     422         169 :   if (!DefinedGlobals.empty())
     423         166 :     thinLTOInternalizeModule(Mod, DefinedGlobals);
     424             : 
     425         241 :   if (Conf.PostInternalizeModuleHook &&
     426         482 :       !Conf.PostInternalizeModuleHook(Task, Mod))
     427           0 :     return Error::success();
     428             : 
     429          54 :   auto ModuleLoader = [&](StringRef Identifier) {
     430             :     assert(Mod.getContext().isODRUniquingDebugTypes() &&
     431             :            "ODR Type uniquing should be enabled on the context");
     432          54 :     auto I = ModuleMap.find(Identifier);
     433             :     assert(I != ModuleMap.end());
     434         108 :     return I->second.getLazyModule(Mod.getContext(),
     435             :                                    /*ShouldLazyLoadMetadata=*/true,
     436         108 :                                    /*IsImporting*/ true);
     437         169 :   };
     438             : 
     439         507 :   FunctionImporter Importer(CombinedIndex, ModuleLoader);
     440         845 :   if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
     441           0 :     return Err;
     442             : 
     443         410 :   if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
     444           0 :     return Error::success();
     445             : 
     446         169 :   if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
     447             :            /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
     448           0 :     return Error::success();
     449             : 
     450         506 :   codegen(Conf, TM.get(), AddStream, Task, Mod);
     451         504 :   return Error::success();
     452             : }

Generated by: LCOV version 1.13