brintos

brintos / llvm-project-archived public Read only

0
0
Text · 48.0 KiB · ff94c54 Raw
1219 lines · cpp
1//===-ThinLTOCodeGenerator.cpp - LLVM Link Time Optimizer -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Thin Link Time Optimization library. This library is10// intended to be used by linker to optimize code at link time.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"15#include "llvm/Support/CommandLine.h"16 17#include "llvm/ADT/ScopeExit.h"18#include "llvm/ADT/Statistic.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/Analysis/ModuleSummaryAnalysis.h"21#include "llvm/Analysis/ProfileSummaryInfo.h"22#include "llvm/Analysis/TargetLibraryInfo.h"23#include "llvm/Bitcode/BitcodeReader.h"24#include "llvm/Bitcode/BitcodeWriter.h"25#include "llvm/Bitcode/BitcodeWriterPass.h"26#include "llvm/Config/llvm-config.h"27#include "llvm/IR/DebugInfo.h"28#include "llvm/IR/DiagnosticPrinter.h"29#include "llvm/IR/LLVMContext.h"30#include "llvm/IR/LLVMRemarkStreamer.h"31#include "llvm/IR/LegacyPassManager.h"32#include "llvm/IR/Mangler.h"33#include "llvm/IR/PassTimingInfo.h"34#include "llvm/IR/Verifier.h"35#include "llvm/IRReader/IRReader.h"36#include "llvm/LTO/LTO.h"37#include "llvm/MC/TargetRegistry.h"38#include "llvm/Object/IRObjectFile.h"39#include "llvm/Passes/PassBuilder.h"40#include "llvm/Passes/StandardInstrumentations.h"41#include "llvm/Remarks/HotnessThresholdParser.h"42#include "llvm/Support/CachePruning.h"43#include "llvm/Support/Debug.h"44#include "llvm/Support/Error.h"45#include "llvm/Support/FileSystem.h"46#include "llvm/Support/FormatVariadic.h"47#include "llvm/Support/Path.h"48#include "llvm/Support/SHA1.h"49#include "llvm/Support/SmallVectorMemoryBuffer.h"50#include "llvm/Support/ThreadPool.h"51#include "llvm/Support/Threading.h"52#include "llvm/Support/ToolOutputFile.h"53#include "llvm/Support/raw_ostream.h"54#include "llvm/Target/TargetMachine.h"55#include "llvm/TargetParser/SubtargetFeature.h"56#include "llvm/Transforms/IPO/FunctionAttrs.h"57#include "llvm/Transforms/IPO/FunctionImport.h"58#include "llvm/Transforms/IPO/Internalize.h"59#include "llvm/Transforms/IPO/WholeProgramDevirt.h"60#include "llvm/Transforms/Utils/FunctionImportUtils.h"61 62#if !defined(_MSC_VER) && !defined(__MINGW32__)63#include <unistd.h>64#else65#include <io.h>66#endif67 68using namespace llvm;69using namespace ThinLTOCodeGeneratorImpl;70 71#define DEBUG_TYPE "thinlto"72 73namespace llvm {74// Flags -discard-value-names, defined in LTOCodeGenerator.cpp75extern cl::opt<bool> LTODiscardValueNames;76extern cl::opt<std::string> RemarksFilename;77extern cl::opt<std::string> RemarksPasses;78extern cl::opt<bool> RemarksWithHotness;79extern cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>80    RemarksHotnessThreshold;81extern cl::opt<std::string> RemarksFormat;82}83 84// Default to using all available threads in the system, but using only one85// thred per core, as indicated by the usage of86// heavyweight_hardware_concurrency() below.87static cl::opt<int> ThreadCount("threads", cl::init(0));88 89// Simple helper to save temporary files for debug.90static void saveTempBitcode(const Module &TheModule, StringRef TempDir,91                            unsigned count, StringRef Suffix) {92  if (TempDir.empty())93    return;94  // User asked to save temps, let dump the bitcode file after import.95  std::string SaveTempPath = (TempDir + llvm::Twine(count) + Suffix).str();96  std::error_code EC;97  raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);98  if (EC)99    report_fatal_error(Twine("Failed to open ") + SaveTempPath +100                       " to save optimized bitcode\n");101  WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);102}103 104static const GlobalValueSummary *getFirstDefinitionForLinker(105    ArrayRef<std::unique_ptr<GlobalValueSummary>> GVSummaryList) {106  // If there is any strong definition anywhere, get it.107  auto StrongDefForLinker = llvm::find_if(108      GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {109        auto Linkage = Summary->linkage();110        return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&111               !GlobalValue::isWeakForLinker(Linkage);112      });113  if (StrongDefForLinker != GVSummaryList.end())114    return StrongDefForLinker->get();115  // Get the first *linker visible* definition for this global in the summary116  // list.117  auto FirstDefForLinker = llvm::find_if(118      GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {119        auto Linkage = Summary->linkage();120        return !GlobalValue::isAvailableExternallyLinkage(Linkage);121      });122  // Extern templates can be emitted as available_externally.123  if (FirstDefForLinker == GVSummaryList.end())124    return nullptr;125  return FirstDefForLinker->get();126}127 128// Populate map of GUID to the prevailing copy for any multiply defined129// symbols. Currently assume first copy is prevailing, or any strong130// definition. Can be refined with Linker information in the future.131static void computePrevailingCopies(132    const ModuleSummaryIndex &Index,133    DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy) {134  auto HasMultipleCopies =135      [&](ArrayRef<std::unique_ptr<GlobalValueSummary>> GVSummaryList) {136        return GVSummaryList.size() > 1;137      };138 139  for (auto &I : Index) {140    if (HasMultipleCopies(I.second.getSummaryList()))141      PrevailingCopy[I.first] =142          getFirstDefinitionForLinker(I.second.getSummaryList());143  }144}145 146static StringMap<lto::InputFile *>147generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {148  StringMap<lto::InputFile *> ModuleMap;149  for (auto &M : Modules) {150    LLVM_DEBUG(dbgs() << "Adding module " << M->getName() << " to ModuleMap\n");151    assert(!ModuleMap.contains(M->getName()) &&152           "Expect unique Buffer Identifier");153    ModuleMap[M->getName()] = M.get();154  }155  return ModuleMap;156}157 158static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,159                          bool ClearDSOLocalOnDeclarations) {160  renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations);161}162 163namespace {164class ThinLTODiagnosticInfo : public DiagnosticInfo {165  const Twine &Msg;166public:167  ThinLTODiagnosticInfo(const Twine &DiagMsg LLVM_LIFETIME_BOUND,168                        DiagnosticSeverity Severity = DS_Error)169      : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}170  void print(DiagnosticPrinter &DP) const override { DP << Msg; }171};172}173 174/// Verify the module and strip broken debug info.175static void verifyLoadedModule(Module &TheModule) {176  bool BrokenDebugInfo = false;177  if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))178    report_fatal_error("Broken module found, compilation aborted!");179  if (BrokenDebugInfo) {180    TheModule.getContext().diagnose(ThinLTODiagnosticInfo(181        "Invalid debug info found, debug info will be stripped", DS_Warning));182    StripDebugInfo(TheModule);183  }184}185 186static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,187                                                   LLVMContext &Context,188                                                   bool Lazy,189                                                   bool IsImporting) {190  auto &Mod = Input->getSingleBitcodeModule();191  SMDiagnostic Err;192  Expected<std::unique_ptr<Module>> ModuleOrErr =193      Lazy ? Mod.getLazyModule(Context,194                               /* ShouldLazyLoadMetadata */ true, IsImporting)195           : Mod.parseModule(Context);196  if (!ModuleOrErr) {197    handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {198      SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),199                                      SourceMgr::DK_Error, EIB.message());200      Err.print("ThinLTO", errs());201    });202    report_fatal_error("Can't load module, abort.");203  }204  if (!Lazy)205    verifyLoadedModule(*ModuleOrErr.get());206  return std::move(*ModuleOrErr);207}208 209static void210crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,211                      StringMap<lto::InputFile *> &ModuleMap,212                      const FunctionImporter::ImportMapTy &ImportList,213                      bool ClearDSOLocalOnDeclarations) {214  auto Loader = [&](StringRef Identifier) {215    auto &Input = ModuleMap[Identifier];216    return loadModuleFromInput(Input, TheModule.getContext(),217                               /*Lazy=*/true, /*IsImporting*/ true);218  };219 220  FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);221  Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);222  if (!Result) {223    handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {224      SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),225                                      SourceMgr::DK_Error, EIB.message());226      Err.print("ThinLTO", errs());227    });228    report_fatal_error("importFunctions failed");229  }230  // Verify again after cross-importing.231  verifyLoadedModule(TheModule);232}233 234static void optimizeModule(Module &TheModule, TargetMachine &TM,235                           unsigned OptLevel, bool Freestanding,236                           bool DebugPassManager, ModuleSummaryIndex *Index) {237  std::optional<PGOOptions> PGOOpt;238  LoopAnalysisManager LAM;239  FunctionAnalysisManager FAM;240  CGSCCAnalysisManager CGAM;241  ModuleAnalysisManager MAM;242 243  PassInstrumentationCallbacks PIC;244  StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);245  SI.registerCallbacks(PIC, &MAM);246  PipelineTuningOptions PTO;247  PTO.LoopVectorization = true;248  PTO.SLPVectorization = true;249  PassBuilder PB(&TM, PTO, PGOOpt, &PIC);250 251  std::unique_ptr<TargetLibraryInfoImpl> TLII(252      new TargetLibraryInfoImpl(TM.getTargetTriple()));253  if (Freestanding)254    TLII->disableAllFunctions();255  FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });256 257  // Register all the basic analyses with the managers.258  PB.registerModuleAnalyses(MAM);259  PB.registerCGSCCAnalyses(CGAM);260  PB.registerFunctionAnalyses(FAM);261  PB.registerLoopAnalyses(LAM);262  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);263 264  ModulePassManager MPM;265 266  OptimizationLevel OL;267 268  switch (OptLevel) {269  default:270    llvm_unreachable("Invalid optimization level");271  case 0:272    OL = OptimizationLevel::O0;273    break;274  case 1:275    OL = OptimizationLevel::O1;276    break;277  case 2:278    OL = OptimizationLevel::O2;279    break;280  case 3:281    OL = OptimizationLevel::O3;282    break;283  }284 285  MPM.addPass(PB.buildThinLTODefaultPipeline(OL, Index));286 287  MPM.run(TheModule, MAM);288}289 290static void291addUsedSymbolToPreservedGUID(const lto::InputFile &File,292                             DenseSet<GlobalValue::GUID> &PreservedGUID) {293  for (const auto &Sym : File.symbols()) {294    if (Sym.isUsed())295      PreservedGUID.insert(296          GlobalValue::getGUIDAssumingExternalLinkage(Sym.getIRName()));297  }298}299 300// Convert the PreservedSymbols map from "Name" based to "GUID" based.301static void computeGUIDPreservedSymbols(const lto::InputFile &File,302                                        const StringSet<> &PreservedSymbols,303                                        const Triple &TheTriple,304                                        DenseSet<GlobalValue::GUID> &GUIDs) {305  // Iterate the symbols in the input file and if the input has preserved symbol306  // compute the GUID for the symbol.307  for (const auto &Sym : File.symbols()) {308    if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())309      GUIDs.insert(GlobalValue::getGUIDAssumingExternalLinkage(310          GlobalValue::getGlobalIdentifier(Sym.getIRName(),311                                           GlobalValue::ExternalLinkage, "")));312  }313}314 315static DenseSet<GlobalValue::GUID>316computeGUIDPreservedSymbols(const lto::InputFile &File,317                            const StringSet<> &PreservedSymbols,318                            const Triple &TheTriple) {319  DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());320  computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,321                              GUIDPreservedSymbols);322  return GUIDPreservedSymbols;323}324 325static std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,326                                                   TargetMachine &TM) {327  SmallVector<char, 128> OutputBuffer;328 329  // CodeGen330  {331    raw_svector_ostream OS(OutputBuffer);332    legacy::PassManager PM;333 334    // Setup the codegen now.335    if (TM.addPassesToEmitFile(PM, OS, nullptr, CodeGenFileType::ObjectFile,336                               /* DisableVerify */ true))337      report_fatal_error("Failed to setup codegen");338 339    // Run codegen now. resulting binary is in OutputBuffer.340    PM.run(TheModule);341  }342  return std::make_unique<SmallVectorMemoryBuffer>(343      std::move(OutputBuffer), /*RequiresNullTerminator=*/false);344}345 346namespace {347/// Manage caching for a single Module.348class ModuleCacheEntry {349  SmallString<128> EntryPath;350 351public:352  // Create a cache entry. This compute a unique hash for the Module considering353  // the current list of export/import, and offer an interface to query to354  // access the content in the cache.355  ModuleCacheEntry(356      StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,357      const FunctionImporter::ImportMapTy &ImportList,358      const FunctionImporter::ExportSetTy &ExportList,359      const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,360      const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,361      bool Freestanding, const TargetMachineBuilder &TMBuilder) {362    if (CachePath.empty())363      return;364 365    if (!Index.modulePaths().count(ModuleID))366      // The module does not have an entry, it can't have a hash at all367      return;368 369    if (all_of(Index.getModuleHash(ModuleID),370               [](uint32_t V) { return V == 0; }))371      // No hash entry, no caching!372      return;373 374    llvm::lto::Config Conf;375    Conf.OptLevel = OptLevel;376    Conf.Options = TMBuilder.Options;377    Conf.CPU = TMBuilder.MCpu;378    Conf.MAttrs.push_back(TMBuilder.MAttr);379    Conf.RelocModel = TMBuilder.RelocModel;380    Conf.CGOptLevel = TMBuilder.CGOptLevel;381    Conf.Freestanding = Freestanding;382    std::string Key =383        computeLTOCacheKey(Conf, Index, ModuleID, ImportList, ExportList,384                           ResolvedODR, DefinedGVSummaries);385 386    // This choice of file name allows the cache to be pruned (see pruneCache()387    // in include/llvm/Support/CachePruning.h).388    sys::path::append(EntryPath, CachePath, Twine("llvmcache-", Key));389  }390 391  // Access the path to this entry in the cache.392  StringRef getEntryPath() { return EntryPath; }393 394  // Try loading the buffer for this cache entry.395  ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {396    if (EntryPath.empty())397      return std::error_code();398    SmallString<64> ResultPath;399    Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForRead(400        Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);401    if (!FDOrErr)402      return errorToErrorCode(FDOrErr.takeError());403    ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getOpenFile(404        *FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);405    sys::fs::closeFile(*FDOrErr);406    return MBOrErr;407  }408 409  // Cache the Produced object file410  void write(const MemoryBuffer &OutputBuffer) {411    if (EntryPath.empty())412      return;413 414    if (auto Err = llvm::writeToOutput(415            EntryPath, [&OutputBuffer](llvm::raw_ostream &OS) -> llvm::Error {416              OS << OutputBuffer.getBuffer();417              return llvm::Error::success();418            }))419      report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",420                                       EntryPath,421                                       toString(std::move(Err)).c_str()));422  }423};424} // end anonymous namespace425 426static std::unique_ptr<MemoryBuffer>427ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,428                     StringMap<lto::InputFile *> &ModuleMap, TargetMachine &TM,429                     const FunctionImporter::ImportMapTy &ImportList,430                     const FunctionImporter::ExportSetTy &ExportList,431                     const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,432                     const GVSummaryMapTy &DefinedGlobals,433                     const ThinLTOCodeGenerator::CachingOptions &CacheOptions,434                     bool DisableCodeGen, StringRef SaveTempsDir,435                     bool Freestanding, unsigned OptLevel, unsigned count,436                     bool DebugPassManager) {437  // "Benchmark"-like optimization: single-source case438  bool SingleModule = (ModuleMap.size() == 1);439 440  // When linking an ELF shared object, dso_local should be dropped. We441  // conservatively do this for -fpic.442  bool ClearDSOLocalOnDeclarations =443      TM.getTargetTriple().isOSBinFormatELF() &&444      TM.getRelocationModel() != Reloc::Static &&445      TheModule.getPIELevel() == PIELevel::Default;446 447  if (!SingleModule) {448    promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);449 450    // Apply summary-based prevailing-symbol resolution decisions.451    thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);452 453    // Save temps: after promotion.454    saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");455  }456 457  // Be friendly and don't nuke totally the module when the client didn't458  // supply anything to preserve.459  if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {460    // Apply summary-based internalization decisions.461    thinLTOInternalizeModule(TheModule, DefinedGlobals);462  }463 464  // Save internalized bitcode465  saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");466 467  if (!SingleModule)468    crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,469                          ClearDSOLocalOnDeclarations);470 471  // Do this after any importing so that imported code is updated.472  // See comment at call to updateVCallVisibilityInIndex() for why473  // WholeProgramVisibilityEnabledInLTO is false.474  updatePublicTypeTestCalls(TheModule,475                            /* WholeProgramVisibilityEnabledInLTO */ false);476 477  // Save temps: after cross-module import.478  saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");479 480  optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,481                 &Index);482 483  saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");484 485  if (DisableCodeGen) {486    // Configured to stop before CodeGen, serialize the bitcode and return.487    SmallVector<char, 128> OutputBuffer;488    {489      raw_svector_ostream OS(OutputBuffer);490      ProfileSummaryInfo PSI(TheModule);491      auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);492      WriteBitcodeToFile(TheModule, OS, true, &Index);493    }494    return std::make_unique<SmallVectorMemoryBuffer>(495        std::move(OutputBuffer), /*RequiresNullTerminator=*/false);496  }497 498  return codegenModule(TheModule, TM);499}500 501/// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map502/// for caching, and in the \p Index for application during the ThinLTO503/// backends. This is needed for correctness for exported symbols (ensure504/// at least one copy kept) and a compile-time optimization (to drop duplicate505/// copies when possible).506static void resolvePrevailingInIndex(507    ModuleSummaryIndex &Index,508    StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>509        &ResolvedODR,510    const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,511    const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>512        &PrevailingCopy) {513 514  auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {515    const auto &Prevailing = PrevailingCopy.find(GUID);516    // Not in map means that there was only one copy, which must be prevailing.517    if (Prevailing == PrevailingCopy.end())518      return true;519    return Prevailing->second == S;520  };521 522  auto recordNewLinkage = [&](StringRef ModuleIdentifier,523                              GlobalValue::GUID GUID,524                              GlobalValue::LinkageTypes NewLinkage) {525    ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;526  };527 528  // TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.529  lto::Config Conf;530  thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,531                                  GUIDPreservedSymbols);532}533 534// Initialize the TargetMachine builder for a given Triple535static void initTMBuilder(TargetMachineBuilder &TMBuilder,536                          const Triple &TheTriple) {537  if (TMBuilder.MCpu.empty())538    TMBuilder.MCpu = lto::getThinLTODefaultCPU(TheTriple);539  TMBuilder.TheTriple = std::move(TheTriple);540}541 542void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {543  MemoryBufferRef Buffer(Data, Identifier);544 545  auto InputOrError = lto::InputFile::create(Buffer);546  if (!InputOrError)547    report_fatal_error(Twine("ThinLTO cannot create input file: ") +548                       toString(InputOrError.takeError()));549 550  auto TripleStr = (*InputOrError)->getTargetTriple();551  Triple TheTriple(TripleStr);552 553  if (Modules.empty())554    initTMBuilder(TMBuilder, Triple(TheTriple));555  else if (TMBuilder.TheTriple != TheTriple) {556    if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))557      report_fatal_error("ThinLTO modules with incompatible triples not "558                         "supported");559    initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));560  }561 562  Modules.emplace_back(std::move(*InputOrError));563}564 565void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {566  PreservedSymbols.insert(Name);567}568 569void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {570  // FIXME: At the moment, we don't take advantage of this extra information,571  // we're conservatively considering cross-references as preserved.572  //  CrossReferencedSymbols.insert(Name);573  PreservedSymbols.insert(Name);574}575 576// TargetMachine factory577std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {578  std::string ErrMsg;579  const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, ErrMsg);580  if (!TheTarget) {581    report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);582  }583 584  // Use MAttr as the default set of features.585  SubtargetFeatures Features(MAttr);586  Features.getDefaultSubtargetFeatures(TheTriple);587  std::string FeatureStr = Features.getString();588 589  std::unique_ptr<TargetMachine> TM(590      TheTarget->createTargetMachine(TheTriple, MCpu, FeatureStr, Options,591                                     RelocModel, std::nullopt, CGOptLevel));592  assert(TM && "Cannot create target machine");593 594  return TM;595}596 597/**598 * Produce the combined summary index from all the bitcode files:599 * "thin-link".600 */601std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {602  std::unique_ptr<ModuleSummaryIndex> CombinedIndex =603      std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);604  for (auto &Mod : Modules) {605    auto &M = Mod->getSingleBitcodeModule();606    if (Error Err = M.readSummary(*CombinedIndex, Mod->getName())) {607      // FIXME diagnose608      logAllUnhandledErrors(609          std::move(Err), errs(),610          "error: can't create module summary index for buffer: ");611      return nullptr;612    }613  }614  return CombinedIndex;615}616 617namespace {618struct IsExported {619  const DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists;620  const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;621 622  IsExported(623      const DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists,624      const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)625      : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}626 627  bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {628    const auto &ExportList = ExportLists.find(ModuleIdentifier);629    return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||630           GUIDPreservedSymbols.count(VI.getGUID());631  }632};633 634struct IsPrevailing {635  const DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy;636  IsPrevailing(const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>637                   &PrevailingCopy)638      : PrevailingCopy(PrevailingCopy) {}639 640  bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {641    const auto &Prevailing = PrevailingCopy.find(GUID);642    // Not in map means that there was only one copy, which must be prevailing.643    if (Prevailing == PrevailingCopy.end())644      return true;645    return Prevailing->second == S;646  };647};648} // namespace649 650static void computeDeadSymbolsInIndex(651    ModuleSummaryIndex &Index,652    const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {653  // We have no symbols resolution available. And can't do any better now in the654  // case where the prevailing symbol is in a native object. It can be refined655  // with linker information in the future.656  auto isPrevailing = [&](GlobalValue::GUID G) {657    return PrevailingType::Unknown;658  };659  computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,660                                  /* ImportEnabled = */ true);661}662 663/**664 * Perform promotion and renaming of exported internal functions.665 * Index is updated to reflect linkage changes from weak resolution.666 */667void ThinLTOCodeGenerator::promote(Module &TheModule, ModuleSummaryIndex &Index,668                                   const lto::InputFile &File) {669  auto ModuleCount = Index.modulePaths().size();670  auto ModuleIdentifier = TheModule.getModuleIdentifier();671 672  // Collect for each module the list of function it defines (GUID -> Summary).673  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;674  Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);675 676  // Convert the preserved symbols set from string to GUID677  auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(678      File, PreservedSymbols, TheModule.getTargetTriple());679 680  // Add used symbol to the preserved symbols.681  addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);682 683  // Compute "dead" symbols, we don't want to import/export these!684  computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);685 686  // Compute prevailing symbols687  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;688  computePrevailingCopies(Index, PrevailingCopy);689 690  // Generate import/export list691  FunctionImporter::ImportListsTy ImportLists(ModuleCount);692  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);693  ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,694                           IsPrevailing(PrevailingCopy), ImportLists,695                           ExportLists);696 697  // Resolve prevailing symbols698  StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;699  resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,700                           PrevailingCopy);701 702  thinLTOFinalizeInModule(TheModule,703                          ModuleToDefinedGVSummaries[ModuleIdentifier],704                          /*PropagateAttrs=*/false);705 706  // Promote the exported values in the index, so that they are promoted707  // in the module.708  thinLTOInternalizeAndPromoteInIndex(709      Index, IsExported(ExportLists, GUIDPreservedSymbols),710      IsPrevailing(PrevailingCopy));711 712  // FIXME Set ClearDSOLocalOnDeclarations.713  promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);714}715 716/**717 * Perform cross-module importing for the module identified by ModuleIdentifier.718 */719void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,720                                             ModuleSummaryIndex &Index,721                                             const lto::InputFile &File) {722  auto ModuleMap = generateModuleMap(Modules);723  auto ModuleCount = Index.modulePaths().size();724 725  // Collect for each module the list of function it defines (GUID -> Summary).726  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);727  Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);728 729  // Convert the preserved symbols set from string to GUID730  auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(731      File, PreservedSymbols, TheModule.getTargetTriple());732 733  addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);734 735  // Compute "dead" symbols, we don't want to import/export these!736  computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);737 738  // Compute prevailing symbols739  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;740  computePrevailingCopies(Index, PrevailingCopy);741 742  // Generate import/export list743  FunctionImporter::ImportListsTy ImportLists(ModuleCount);744  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);745  ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,746                           IsPrevailing(PrevailingCopy), ImportLists,747                           ExportLists);748  auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];749 750  // FIXME Set ClearDSOLocalOnDeclarations.751  crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,752                        /*ClearDSOLocalOnDeclarations=*/false);753}754 755/**756 * Compute the list of summaries needed for importing into module.757 */758void ThinLTOCodeGenerator::gatherImportedSummariesForModule(759    Module &TheModule, ModuleSummaryIndex &Index,760    ModuleToSummariesForIndexTy &ModuleToSummariesForIndex,761    GVSummaryPtrSet &DecSummaries, const lto::InputFile &File) {762  auto ModuleCount = Index.modulePaths().size();763  auto ModuleIdentifier = TheModule.getModuleIdentifier();764 765  // Collect for each module the list of function it defines (GUID -> Summary).766  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);767  Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);768 769  // Convert the preserved symbols set from string to GUID770  auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(771      File, PreservedSymbols, TheModule.getTargetTriple());772 773  addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);774 775  // Compute "dead" symbols, we don't want to import/export these!776  computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);777 778  // Compute prevailing symbols779  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;780  computePrevailingCopies(Index, PrevailingCopy);781 782  // Generate import/export list783  FunctionImporter::ImportListsTy ImportLists(ModuleCount);784  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);785  ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,786                           IsPrevailing(PrevailingCopy), ImportLists,787                           ExportLists);788 789  llvm::gatherImportedSummariesForModule(790      ModuleIdentifier, ModuleToDefinedGVSummaries,791      ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries);792}793 794/**795 * Emit the list of files needed for importing into module.796 */797void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName,798                                       ModuleSummaryIndex &Index,799                                       const lto::InputFile &File) {800  auto ModuleCount = Index.modulePaths().size();801  auto ModuleIdentifier = TheModule.getModuleIdentifier();802 803  // Collect for each module the list of function it defines (GUID -> Summary).804  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);805  Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);806 807  // Convert the preserved symbols set from string to GUID808  auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(809      File, PreservedSymbols, TheModule.getTargetTriple());810 811  addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);812 813  // Compute "dead" symbols, we don't want to import/export these!814  computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);815 816  // Compute prevailing symbols817  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;818  computePrevailingCopies(Index, PrevailingCopy);819 820  // Generate import/export list821  FunctionImporter::ImportListsTy ImportLists(ModuleCount);822  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);823  ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,824                           IsPrevailing(PrevailingCopy), ImportLists,825                           ExportLists);826 827  // 'EmitImportsFiles' emits the list of modules from which to import from, and828  // the set of keys in `ModuleToSummariesForIndex` should be a superset of keys829  // in `DecSummaries`, so no need to use `DecSummaries` in `EmitImportsFiles`.830  GVSummaryPtrSet DecSummaries;831  ModuleToSummariesForIndexTy ModuleToSummariesForIndex;832  llvm::gatherImportedSummariesForModule(833      ModuleIdentifier, ModuleToDefinedGVSummaries,834      ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries);835 836  if (Error EC = EmitImportsFiles(ModuleIdentifier, OutputName,837                                  ModuleToSummariesForIndex))838    report_fatal_error(Twine("Failed to open ") + OutputName +839                       " to save imports lists\n");840}841 842/**843 * Perform internalization. Runs promote and internalization together.844 * Index is updated to reflect linkage changes.845 */846void ThinLTOCodeGenerator::internalize(Module &TheModule,847                                       ModuleSummaryIndex &Index,848                                       const lto::InputFile &File) {849  initTMBuilder(TMBuilder, TheModule.getTargetTriple());850  auto ModuleCount = Index.modulePaths().size();851  auto ModuleIdentifier = TheModule.getModuleIdentifier();852 853  // Convert the preserved symbols set from string to GUID854  auto GUIDPreservedSymbols =855      computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);856 857  addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);858 859  // Collect for each module the list of function it defines (GUID -> Summary).860  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);861  Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);862 863  // Compute "dead" symbols, we don't want to import/export these!864  computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);865 866  // Compute prevailing symbols867  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;868  computePrevailingCopies(Index, PrevailingCopy);869 870  // Generate import/export list871  FunctionImporter::ImportListsTy ImportLists(ModuleCount);872  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);873  ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,874                           IsPrevailing(PrevailingCopy), ImportLists,875                           ExportLists);876  auto &ExportList = ExportLists[ModuleIdentifier];877 878  // Be friendly and don't nuke totally the module when the client didn't879  // supply anything to preserve.880  if (ExportList.empty() && GUIDPreservedSymbols.empty())881    return;882 883  // Resolve prevailing symbols884  StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;885  resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,886                           PrevailingCopy);887 888  // Promote the exported values in the index, so that they are promoted889  // in the module.890  thinLTOInternalizeAndPromoteInIndex(891      Index, IsExported(ExportLists, GUIDPreservedSymbols),892      IsPrevailing(PrevailingCopy));893 894  // FIXME Set ClearDSOLocalOnDeclarations.895  promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);896 897  // Internalization898  thinLTOFinalizeInModule(TheModule,899                          ModuleToDefinedGVSummaries[ModuleIdentifier],900                          /*PropagateAttrs=*/false);901 902  thinLTOInternalizeModule(TheModule,903                           ModuleToDefinedGVSummaries[ModuleIdentifier]);904}905 906/**907 * Perform post-importing ThinLTO optimizations.908 */909void ThinLTOCodeGenerator::optimize(Module &TheModule) {910  initTMBuilder(TMBuilder, TheModule.getTargetTriple());911 912  // Optimize now913  optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,914                 DebugPassManager, nullptr);915}916 917/// Write out the generated object file, either from CacheEntryPath or from918/// OutputBuffer, preferring hard-link when possible.919/// Returns the path to the generated file in SavedObjectsDirectoryPath.920std::string921ThinLTOCodeGenerator::writeGeneratedObject(int count, StringRef CacheEntryPath,922                                           const MemoryBuffer &OutputBuffer) {923  auto ArchName = TMBuilder.TheTriple.getArchName();924  SmallString<128> OutputPath(SavedObjectsDirectoryPath);925  llvm::sys::path::append(OutputPath,926                          Twine(count) + "." + ArchName + ".thinlto.o");927  OutputPath.c_str(); // Ensure the string is null terminated.928  if (sys::fs::exists(OutputPath))929    sys::fs::remove(OutputPath);930 931  // We don't return a memory buffer to the linker, just a list of files.932  if (!CacheEntryPath.empty()) {933    // Cache is enabled, hard-link the entry (or copy if hard-link fails).934    auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);935    if (!Err)936      return std::string(OutputPath);937    // Hard linking failed, try to copy.938    Err = sys::fs::copy_file(CacheEntryPath, OutputPath);939    if (!Err)940      return std::string(OutputPath);941    // Copy failed (could be because the CacheEntry was removed from the cache942    // in the meantime by another process), fall back and try to write down the943    // buffer to the output.944    errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath945           << "' to '" << OutputPath << "'\n";946  }947  // No cache entry, just write out the buffer.948  std::error_code Err;949  raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);950  if (Err)951    report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");952  OS << OutputBuffer.getBuffer();953  return std::string(OutputPath);954}955 956// Main entry point for the ThinLTO processing957void ThinLTOCodeGenerator::run() {958  timeTraceProfilerBegin("ThinLink", StringRef(""));959  auto TimeTraceScopeExit = llvm::make_scope_exit([]() {960    if (llvm::timeTraceProfilerEnabled())961      llvm::timeTraceProfilerEnd();962  });963  // Prepare the resulting object vector964  assert(ProducedBinaries.empty() && "The generator should not be reused");965  if (SavedObjectsDirectoryPath.empty())966    ProducedBinaries.resize(Modules.size());967  else {968    sys::fs::create_directories(SavedObjectsDirectoryPath);969    bool IsDir;970    sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);971    if (!IsDir)972      report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");973    ProducedBinaryFiles.resize(Modules.size());974  }975 976  if (CodeGenOnly) {977    // Perform only parallel codegen and return.978    DefaultThreadPool Pool;979    int count = 0;980    for (auto &Mod : Modules) {981      Pool.async([&](int count) {982        LLVMContext Context;983        Context.setDiscardValueNames(LTODiscardValueNames);984 985        // Parse module now986        auto TheModule = loadModuleFromInput(Mod.get(), Context, false,987                                             /*IsImporting*/ false);988 989        // CodeGen990        auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());991        if (SavedObjectsDirectoryPath.empty())992          ProducedBinaries[count] = std::move(OutputBuffer);993        else994          ProducedBinaryFiles[count] =995              writeGeneratedObject(count, "", *OutputBuffer);996      }, count++);997    }998 999    return;1000  }1001 1002  // Sequential linking phase1003  auto Index = linkCombinedIndex();1004 1005  // Save temps: index.1006  if (!SaveTempsDir.empty()) {1007    auto SaveTempPath = SaveTempsDir + "index.bc";1008    std::error_code EC;1009    raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);1010    if (EC)1011      report_fatal_error(Twine("Failed to open ") + SaveTempPath +1012                         " to save optimized bitcode\n");1013    writeIndexToFile(*Index, OS);1014  }1015 1016 1017  // Prepare the module map.1018  auto ModuleMap = generateModuleMap(Modules);1019  auto ModuleCount = Modules.size();1020 1021  // Collect for each module the list of function it defines (GUID -> Summary).1022  DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);1023  Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);1024 1025  // Convert the preserved symbols set from string to GUID, this is needed for1026  // computing the caching hash and the internalization.1027  DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;1028  for (const auto &M : Modules)1029    computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,1030                                GUIDPreservedSymbols);1031 1032  // Add used symbol from inputs to the preserved symbols.1033  for (const auto &M : Modules)1034    addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);1035 1036  // Compute "dead" symbols, we don't want to import/export these!1037  computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);1038 1039  // Currently there is no support for enabling whole program visibility via a1040  // linker option in the old LTO API, but this call allows it to be specified1041  // via the internal option. Must be done before WPD below.1042  if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))1043    Index->setWithWholeProgramVisibility();1044 1045  // FIXME: This needs linker information via a TBD new interface1046  updateVCallVisibilityInIndex(*Index,1047                               /*WholeProgramVisibilityEnabledInLTO=*/false,1048                               // FIXME: These need linker information via a1049                               // TBD new interface.1050                               /*DynamicExportSymbols=*/{},1051                               /*VisibleToRegularObjSymbols=*/{});1052 1053  // Perform index-based WPD. This will return immediately if there are1054  // no index entries in the typeIdMetadata map (e.g. if we are instead1055  // performing IR-based WPD in hybrid regular/thin LTO mode).1056  std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;1057  std::set<GlobalValue::GUID> ExportedGUIDs;1058  runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);1059  GUIDPreservedSymbols.insert_range(ExportedGUIDs);1060 1061  // Compute prevailing symbols1062  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;1063  computePrevailingCopies(*Index, PrevailingCopy);1064 1065  // Collect the import/export lists for all modules from the call-graph in the1066  // combined index.1067  FunctionImporter::ImportListsTy ImportLists(ModuleCount);1068  DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);1069  ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries,1070                           IsPrevailing(PrevailingCopy), ImportLists,1071                           ExportLists);1072 1073  // We use a std::map here to be able to have a defined ordering when1074  // producing a hash for the cache entry.1075  // FIXME: we should be able to compute the caching hash for the entry based1076  // on the index, and nuke this map.1077  StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;1078 1079  // Resolve prevailing symbols, this has to be computed early because it1080  // impacts the caching.1081  resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,1082                           PrevailingCopy);1083 1084  // Use global summary-based analysis to identify symbols that can be1085  // internalized (because they aren't exported or preserved as per callback).1086  // Changes are made in the index, consumed in the ThinLTO backends.1087  updateIndexWPDForExports(*Index,1088                           IsExported(ExportLists, GUIDPreservedSymbols),1089                           LocalWPDTargetsMap);1090  thinLTOInternalizeAndPromoteInIndex(1091      *Index, IsExported(ExportLists, GUIDPreservedSymbols),1092      IsPrevailing(PrevailingCopy));1093 1094  thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));1095 1096  // Make sure that every module has an entry in the ExportLists, ImportList,1097  // GVSummary and ResolvedODR maps to enable threaded access to these maps1098  // below.1099  for (auto &Module : Modules) {1100    auto ModuleIdentifier = Module->getName();1101    ExportLists[ModuleIdentifier];1102    ImportLists[ModuleIdentifier];1103    ResolvedODR[ModuleIdentifier];1104    ModuleToDefinedGVSummaries[ModuleIdentifier];1105  }1106 1107  std::vector<BitcodeModule *> ModulesVec;1108  ModulesVec.reserve(Modules.size());1109  for (auto &Mod : Modules)1110    ModulesVec.push_back(&Mod->getSingleBitcodeModule());1111  std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);1112 1113  if (llvm::timeTraceProfilerEnabled())1114    llvm::timeTraceProfilerEnd();1115 1116  TimeTraceScopeExit.release();1117 1118  // Parallel optimizer + codegen1119  {1120    DefaultThreadPool Pool(heavyweight_hardware_concurrency(ThreadCount));1121    for (auto IndexCount : ModulesOrdering) {1122      auto &Mod = Modules[IndexCount];1123      Pool.async([&](int count) {1124        auto ModuleIdentifier = Mod->getName();1125        auto &ExportList = ExportLists[ModuleIdentifier];1126 1127        auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];1128 1129        // The module may be cached, this helps handling it.1130        ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,1131                                    ImportLists[ModuleIdentifier], ExportList,1132                                    ResolvedODR[ModuleIdentifier],1133                                    DefinedGVSummaries, OptLevel, Freestanding,1134                                    TMBuilder);1135        auto CacheEntryPath = CacheEntry.getEntryPath();1136 1137        {1138          auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();1139          LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")1140                            << " '" << CacheEntryPath << "' for buffer "1141                            << count << " " << ModuleIdentifier << "\n");1142 1143          if (ErrOrBuffer) {1144            // Cache Hit!1145            if (SavedObjectsDirectoryPath.empty())1146              ProducedBinaries[count] = std::move(ErrOrBuffer.get());1147            else1148              ProducedBinaryFiles[count] = writeGeneratedObject(1149                  count, CacheEntryPath, *ErrOrBuffer.get());1150            return;1151          }1152        }1153 1154        LLVMContext Context;1155        Context.setDiscardValueNames(LTODiscardValueNames);1156        Context.enableDebugTypeODRUniquing();1157        auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(1158            Context, RemarksFilename, RemarksPasses, RemarksFormat,1159            RemarksWithHotness, RemarksHotnessThreshold, count);1160        if (!DiagFileOrErr) {1161          errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";1162          report_fatal_error("ThinLTO: Can't get an output file for the "1163                             "remarks");1164        }1165 1166        // Parse module now1167        auto TheModule = loadModuleFromInput(Mod.get(), Context, false,1168                                             /*IsImporting*/ false);1169 1170        // Save temps: original file.1171        saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");1172 1173        auto &ImportList = ImportLists[ModuleIdentifier];1174        // Run the main process now, and generates a binary1175        auto OutputBuffer = ProcessThinLTOModule(1176            *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,1177            ExportList, GUIDPreservedSymbols,1178            ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,1179            DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,1180            DebugPassManager);1181 1182        // Commit to the cache (if enabled)1183        CacheEntry.write(*OutputBuffer);1184 1185        if (SavedObjectsDirectoryPath.empty()) {1186          // We need to generated a memory buffer for the linker.1187          if (!CacheEntryPath.empty()) {1188            // When cache is enabled, reload from the cache if possible.1189            // Releasing the buffer from the heap and reloading it from the1190            // cache file with mmap helps us to lower memory pressure.1191            // The freed memory can be used for the next input file.1192            // The final binary link will read from the VFS cache (hopefully!)1193            // or from disk (if the memory pressure was too high).1194            auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();1195            if (auto EC = ReloadedBufferOrErr.getError()) {1196              // On error, keep the preexisting buffer and print a diagnostic.1197              errs() << "remark: can't reload cached file '" << CacheEntryPath1198                     << "': " << EC.message() << "\n";1199            } else {1200              OutputBuffer = std::move(*ReloadedBufferOrErr);1201            }1202          }1203          ProducedBinaries[count] = std::move(OutputBuffer);1204          return;1205        }1206        ProducedBinaryFiles[count] = writeGeneratedObject(1207            count, CacheEntryPath, *OutputBuffer);1208      }, IndexCount);1209    }1210  }1211 1212  pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);1213 1214  // If statistics were requested, print them out now.1215  if (llvm::AreStatisticsEnabled())1216    llvm::PrintStatistics();1217  reportAndResetTimings();1218}1219