Path: blob/main/contrib/llvm-project/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
35233 views
//===-ThinLTOCodeGenerator.cpp - LLVM Link Time Optimizer -----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the Thin Link Time Optimization library. This library is9// intended to be used by linker to optimize code at link time.10//11//===----------------------------------------------------------------------===//1213#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"14#include "llvm/Support/CommandLine.h"1516#include "llvm/ADT/ScopeExit.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/ADT/StringExtras.h"19#include "llvm/Analysis/AliasAnalysis.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/LegacyPassManager.h"30#include "llvm/IR/LLVMContext.h"31#include "llvm/IR/LLVMRemarkStreamer.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/LTO/SummaryBasedOptimizations.h"38#include "llvm/MC/TargetRegistry.h"39#include "llvm/Object/IRObjectFile.h"40#include "llvm/Passes/PassBuilder.h"41#include "llvm/Passes/StandardInstrumentations.h"42#include "llvm/Remarks/HotnessThresholdParser.h"43#include "llvm/Support/CachePruning.h"44#include "llvm/Support/Debug.h"45#include "llvm/Support/Error.h"46#include "llvm/Support/FileSystem.h"47#include "llvm/Support/FormatVariadic.h"48#include "llvm/Support/Path.h"49#include "llvm/Support/SHA1.h"50#include "llvm/Support/SmallVectorMemoryBuffer.h"51#include "llvm/Support/ThreadPool.h"52#include "llvm/Support/Threading.h"53#include "llvm/Support/ToolOutputFile.h"54#include "llvm/Support/raw_ostream.h"55#include "llvm/Target/TargetMachine.h"56#include "llvm/TargetParser/SubtargetFeature.h"57#include "llvm/Transforms/IPO/FunctionAttrs.h"58#include "llvm/Transforms/IPO/FunctionImport.h"59#include "llvm/Transforms/IPO/Internalize.h"60#include "llvm/Transforms/IPO/WholeProgramDevirt.h"61#include "llvm/Transforms/ObjCARC.h"62#include "llvm/Transforms/Utils/FunctionImportUtils.h"6364#include <numeric>6566#if !defined(_MSC_VER) && !defined(__MINGW32__)67#include <unistd.h>68#else69#include <io.h>70#endif7172using namespace llvm;7374#define DEBUG_TYPE "thinlto"7576namespace llvm {77// Flags -discard-value-names, defined in LTOCodeGenerator.cpp78extern cl::opt<bool> LTODiscardValueNames;79extern cl::opt<std::string> RemarksFilename;80extern cl::opt<std::string> RemarksPasses;81extern cl::opt<bool> RemarksWithHotness;82extern cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>83RemarksHotnessThreshold;84extern cl::opt<std::string> RemarksFormat;85}8687namespace {8889// Default to using all available threads in the system, but using only one90// thred per core, as indicated by the usage of91// heavyweight_hardware_concurrency() below.92static cl::opt<int> ThreadCount("threads", cl::init(0));9394// Simple helper to save temporary files for debug.95static void saveTempBitcode(const Module &TheModule, StringRef TempDir,96unsigned count, StringRef Suffix) {97if (TempDir.empty())98return;99// User asked to save temps, let dump the bitcode file after import.100std::string SaveTempPath = (TempDir + llvm::Twine(count) + Suffix).str();101std::error_code EC;102raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);103if (EC)104report_fatal_error(Twine("Failed to open ") + SaveTempPath +105" to save optimized bitcode\n");106WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);107}108109static const GlobalValueSummary *110getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {111// If there is any strong definition anywhere, get it.112auto StrongDefForLinker = llvm::find_if(113GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {114auto Linkage = Summary->linkage();115return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&116!GlobalValue::isWeakForLinker(Linkage);117});118if (StrongDefForLinker != GVSummaryList.end())119return StrongDefForLinker->get();120// Get the first *linker visible* definition for this global in the summary121// list.122auto FirstDefForLinker = llvm::find_if(123GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {124auto Linkage = Summary->linkage();125return !GlobalValue::isAvailableExternallyLinkage(Linkage);126});127// Extern templates can be emitted as available_externally.128if (FirstDefForLinker == GVSummaryList.end())129return nullptr;130return FirstDefForLinker->get();131}132133// Populate map of GUID to the prevailing copy for any multiply defined134// symbols. Currently assume first copy is prevailing, or any strong135// definition. Can be refined with Linker information in the future.136static void computePrevailingCopies(137const ModuleSummaryIndex &Index,138DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy) {139auto HasMultipleCopies = [&](const GlobalValueSummaryList &GVSummaryList) {140return GVSummaryList.size() > 1;141};142143for (auto &I : Index) {144if (HasMultipleCopies(I.second.SummaryList))145PrevailingCopy[I.first] =146getFirstDefinitionForLinker(I.second.SummaryList);147}148}149150static StringMap<lto::InputFile *>151generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {152StringMap<lto::InputFile *> ModuleMap;153for (auto &M : Modules) {154LLVM_DEBUG(dbgs() << "Adding module " << M->getName() << " to ModuleMap\n");155assert(!ModuleMap.contains(M->getName()) &&156"Expect unique Buffer Identifier");157ModuleMap[M->getName()] = M.get();158}159return ModuleMap;160}161162static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,163bool ClearDSOLocalOnDeclarations) {164if (renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations))165report_fatal_error("renameModuleForThinLTO failed");166}167168namespace {169class ThinLTODiagnosticInfo : public DiagnosticInfo {170const Twine &Msg;171public:172ThinLTODiagnosticInfo(const Twine &DiagMsg,173DiagnosticSeverity Severity = DS_Error)174: DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}175void print(DiagnosticPrinter &DP) const override { DP << Msg; }176};177}178179/// Verify the module and strip broken debug info.180static void verifyLoadedModule(Module &TheModule) {181bool BrokenDebugInfo = false;182if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))183report_fatal_error("Broken module found, compilation aborted!");184if (BrokenDebugInfo) {185TheModule.getContext().diagnose(ThinLTODiagnosticInfo(186"Invalid debug info found, debug info will be stripped", DS_Warning));187StripDebugInfo(TheModule);188}189}190191static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,192LLVMContext &Context,193bool Lazy,194bool IsImporting) {195auto &Mod = Input->getSingleBitcodeModule();196SMDiagnostic Err;197Expected<std::unique_ptr<Module>> ModuleOrErr =198Lazy ? Mod.getLazyModule(Context,199/* ShouldLazyLoadMetadata */ true, IsImporting)200: Mod.parseModule(Context);201if (!ModuleOrErr) {202handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {203SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),204SourceMgr::DK_Error, EIB.message());205Err.print("ThinLTO", errs());206});207report_fatal_error("Can't load module, abort.");208}209if (!Lazy)210verifyLoadedModule(*ModuleOrErr.get());211return std::move(*ModuleOrErr);212}213214static void215crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,216StringMap<lto::InputFile *> &ModuleMap,217const FunctionImporter::ImportMapTy &ImportList,218bool ClearDSOLocalOnDeclarations) {219auto Loader = [&](StringRef Identifier) {220auto &Input = ModuleMap[Identifier];221return loadModuleFromInput(Input, TheModule.getContext(),222/*Lazy=*/true, /*IsImporting*/ true);223};224225FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);226Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);227if (!Result) {228handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {229SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),230SourceMgr::DK_Error, EIB.message());231Err.print("ThinLTO", errs());232});233report_fatal_error("importFunctions failed");234}235// Verify again after cross-importing.236verifyLoadedModule(TheModule);237}238239static void optimizeModule(Module &TheModule, TargetMachine &TM,240unsigned OptLevel, bool Freestanding,241bool DebugPassManager, ModuleSummaryIndex *Index) {242std::optional<PGOOptions> PGOOpt;243LoopAnalysisManager LAM;244FunctionAnalysisManager FAM;245CGSCCAnalysisManager CGAM;246ModuleAnalysisManager MAM;247248PassInstrumentationCallbacks PIC;249StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);250SI.registerCallbacks(PIC, &MAM);251PipelineTuningOptions PTO;252PTO.LoopVectorization = true;253PTO.SLPVectorization = true;254PassBuilder PB(&TM, PTO, PGOOpt, &PIC);255256std::unique_ptr<TargetLibraryInfoImpl> TLII(257new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())));258if (Freestanding)259TLII->disableAllFunctions();260FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });261262// Register all the basic analyses with the managers.263PB.registerModuleAnalyses(MAM);264PB.registerCGSCCAnalyses(CGAM);265PB.registerFunctionAnalyses(FAM);266PB.registerLoopAnalyses(LAM);267PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);268269ModulePassManager MPM;270271OptimizationLevel OL;272273switch (OptLevel) {274default:275llvm_unreachable("Invalid optimization level");276case 0:277OL = OptimizationLevel::O0;278break;279case 1:280OL = OptimizationLevel::O1;281break;282case 2:283OL = OptimizationLevel::O2;284break;285case 3:286OL = OptimizationLevel::O3;287break;288}289290MPM.addPass(PB.buildThinLTODefaultPipeline(OL, Index));291292MPM.run(TheModule, MAM);293}294295static void296addUsedSymbolToPreservedGUID(const lto::InputFile &File,297DenseSet<GlobalValue::GUID> &PreservedGUID) {298for (const auto &Sym : File.symbols()) {299if (Sym.isUsed())300PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));301}302}303304// Convert the PreservedSymbols map from "Name" based to "GUID" based.305static void computeGUIDPreservedSymbols(const lto::InputFile &File,306const StringSet<> &PreservedSymbols,307const Triple &TheTriple,308DenseSet<GlobalValue::GUID> &GUIDs) {309// Iterate the symbols in the input file and if the input has preserved symbol310// compute the GUID for the symbol.311for (const auto &Sym : File.symbols()) {312if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())313GUIDs.insert(GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(314Sym.getIRName(), GlobalValue::ExternalLinkage, "")));315}316}317318static DenseSet<GlobalValue::GUID>319computeGUIDPreservedSymbols(const lto::InputFile &File,320const StringSet<> &PreservedSymbols,321const Triple &TheTriple) {322DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());323computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,324GUIDPreservedSymbols);325return GUIDPreservedSymbols;326}327328std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,329TargetMachine &TM) {330SmallVector<char, 128> OutputBuffer;331332// CodeGen333{334raw_svector_ostream OS(OutputBuffer);335legacy::PassManager PM;336337// If the bitcode files contain ARC code and were compiled with optimization,338// the ObjCARCContractPass must be run, so do it unconditionally here.339PM.add(createObjCARCContractPass());340341// Setup the codegen now.342if (TM.addPassesToEmitFile(PM, OS, nullptr, CodeGenFileType::ObjectFile,343/* DisableVerify */ true))344report_fatal_error("Failed to setup codegen");345346// Run codegen now. resulting binary is in OutputBuffer.347PM.run(TheModule);348}349return std::make_unique<SmallVectorMemoryBuffer>(350std::move(OutputBuffer), /*RequiresNullTerminator=*/false);351}352353/// Manage caching for a single Module.354class ModuleCacheEntry {355SmallString<128> EntryPath;356357public:358// Create a cache entry. This compute a unique hash for the Module considering359// the current list of export/import, and offer an interface to query to360// access the content in the cache.361ModuleCacheEntry(362StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,363const FunctionImporter::ImportMapTy &ImportList,364const FunctionImporter::ExportSetTy &ExportList,365const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,366const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,367bool Freestanding, const TargetMachineBuilder &TMBuilder) {368if (CachePath.empty())369return;370371if (!Index.modulePaths().count(ModuleID))372// The module does not have an entry, it can't have a hash at all373return;374375if (all_of(Index.getModuleHash(ModuleID),376[](uint32_t V) { return V == 0; }))377// No hash entry, no caching!378return;379380llvm::lto::Config Conf;381Conf.OptLevel = OptLevel;382Conf.Options = TMBuilder.Options;383Conf.CPU = TMBuilder.MCpu;384Conf.MAttrs.push_back(TMBuilder.MAttr);385Conf.RelocModel = TMBuilder.RelocModel;386Conf.CGOptLevel = TMBuilder.CGOptLevel;387Conf.Freestanding = Freestanding;388SmallString<40> Key;389computeLTOCacheKey(Key, Conf, Index, ModuleID, ImportList, ExportList,390ResolvedODR, DefinedGVSummaries);391392// This choice of file name allows the cache to be pruned (see pruneCache()393// in include/llvm/Support/CachePruning.h).394sys::path::append(EntryPath, CachePath, "llvmcache-" + Key);395}396397// Access the path to this entry in the cache.398StringRef getEntryPath() { return EntryPath; }399400// Try loading the buffer for this cache entry.401ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {402if (EntryPath.empty())403return std::error_code();404SmallString<64> ResultPath;405Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForRead(406Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);407if (!FDOrErr)408return errorToErrorCode(FDOrErr.takeError());409ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getOpenFile(410*FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);411sys::fs::closeFile(*FDOrErr);412return MBOrErr;413}414415// Cache the Produced object file416void write(const MemoryBuffer &OutputBuffer) {417if (EntryPath.empty())418return;419420if (auto Err = llvm::writeToOutput(421EntryPath, [&OutputBuffer](llvm::raw_ostream &OS) -> llvm::Error {422OS << OutputBuffer.getBuffer();423return llvm::Error::success();424}))425report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",426EntryPath,427toString(std::move(Err)).c_str()));428}429};430431static std::unique_ptr<MemoryBuffer>432ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,433StringMap<lto::InputFile *> &ModuleMap, TargetMachine &TM,434const FunctionImporter::ImportMapTy &ImportList,435const FunctionImporter::ExportSetTy &ExportList,436const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,437const GVSummaryMapTy &DefinedGlobals,438const ThinLTOCodeGenerator::CachingOptions &CacheOptions,439bool DisableCodeGen, StringRef SaveTempsDir,440bool Freestanding, unsigned OptLevel, unsigned count,441bool DebugPassManager) {442// "Benchmark"-like optimization: single-source case443bool SingleModule = (ModuleMap.size() == 1);444445// When linking an ELF shared object, dso_local should be dropped. We446// conservatively do this for -fpic.447bool ClearDSOLocalOnDeclarations =448TM.getTargetTriple().isOSBinFormatELF() &&449TM.getRelocationModel() != Reloc::Static &&450TheModule.getPIELevel() == PIELevel::Default;451452if (!SingleModule) {453promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);454455// Apply summary-based prevailing-symbol resolution decisions.456thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);457458// Save temps: after promotion.459saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");460}461462// Be friendly and don't nuke totally the module when the client didn't463// supply anything to preserve.464if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {465// Apply summary-based internalization decisions.466thinLTOInternalizeModule(TheModule, DefinedGlobals);467}468469// Save internalized bitcode470saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");471472if (!SingleModule)473crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,474ClearDSOLocalOnDeclarations);475476// Do this after any importing so that imported code is updated.477// See comment at call to updateVCallVisibilityInIndex() for why478// WholeProgramVisibilityEnabledInLTO is false.479updatePublicTypeTestCalls(TheModule,480/* WholeProgramVisibilityEnabledInLTO */ false);481482// Save temps: after cross-module import.483saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");484485optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,486&Index);487488saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");489490if (DisableCodeGen) {491// Configured to stop before CodeGen, serialize the bitcode and return.492SmallVector<char, 128> OutputBuffer;493{494raw_svector_ostream OS(OutputBuffer);495ProfileSummaryInfo PSI(TheModule);496auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);497WriteBitcodeToFile(TheModule, OS, true, &Index);498}499return std::make_unique<SmallVectorMemoryBuffer>(500std::move(OutputBuffer), /*RequiresNullTerminator=*/false);501}502503return codegenModule(TheModule, TM);504}505506/// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map507/// for caching, and in the \p Index for application during the ThinLTO508/// backends. This is needed for correctness for exported symbols (ensure509/// at least one copy kept) and a compile-time optimization (to drop duplicate510/// copies when possible).511static void resolvePrevailingInIndex(512ModuleSummaryIndex &Index,513StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>514&ResolvedODR,515const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,516const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>517&PrevailingCopy) {518519auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {520const auto &Prevailing = PrevailingCopy.find(GUID);521// Not in map means that there was only one copy, which must be prevailing.522if (Prevailing == PrevailingCopy.end())523return true;524return Prevailing->second == S;525};526527auto recordNewLinkage = [&](StringRef ModuleIdentifier,528GlobalValue::GUID GUID,529GlobalValue::LinkageTypes NewLinkage) {530ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;531};532533// TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.534lto::Config Conf;535thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,536GUIDPreservedSymbols);537}538539// Initialize the TargetMachine builder for a given Triple540static void initTMBuilder(TargetMachineBuilder &TMBuilder,541const Triple &TheTriple) {542if (TMBuilder.MCpu.empty())543TMBuilder.MCpu = lto::getThinLTODefaultCPU(TheTriple);544TMBuilder.TheTriple = std::move(TheTriple);545}546547} // end anonymous namespace548549void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {550MemoryBufferRef Buffer(Data, Identifier);551552auto InputOrError = lto::InputFile::create(Buffer);553if (!InputOrError)554report_fatal_error(Twine("ThinLTO cannot create input file: ") +555toString(InputOrError.takeError()));556557auto TripleStr = (*InputOrError)->getTargetTriple();558Triple TheTriple(TripleStr);559560if (Modules.empty())561initTMBuilder(TMBuilder, Triple(TheTriple));562else if (TMBuilder.TheTriple != TheTriple) {563if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))564report_fatal_error("ThinLTO modules with incompatible triples not "565"supported");566initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));567}568569Modules.emplace_back(std::move(*InputOrError));570}571572void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {573PreservedSymbols.insert(Name);574}575576void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {577// FIXME: At the moment, we don't take advantage of this extra information,578// we're conservatively considering cross-references as preserved.579// CrossReferencedSymbols.insert(Name);580PreservedSymbols.insert(Name);581}582583// TargetMachine factory584std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {585std::string ErrMsg;586const Target *TheTarget =587TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);588if (!TheTarget) {589report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);590}591592// Use MAttr as the default set of features.593SubtargetFeatures Features(MAttr);594Features.getDefaultSubtargetFeatures(TheTriple);595std::string FeatureStr = Features.getString();596597std::unique_ptr<TargetMachine> TM(598TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,599RelocModel, std::nullopt, CGOptLevel));600assert(TM && "Cannot create target machine");601602return TM;603}604605/**606* Produce the combined summary index from all the bitcode files:607* "thin-link".608*/609std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {610std::unique_ptr<ModuleSummaryIndex> CombinedIndex =611std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);612for (auto &Mod : Modules) {613auto &M = Mod->getSingleBitcodeModule();614if (Error Err = M.readSummary(*CombinedIndex, Mod->getName())) {615// FIXME diagnose616logAllUnhandledErrors(617std::move(Err), errs(),618"error: can't create module summary index for buffer: ");619return nullptr;620}621}622return CombinedIndex;623}624625namespace {626struct IsExported {627const DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists;628const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;629630IsExported(631const DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists,632const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)633: ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}634635bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {636const auto &ExportList = ExportLists.find(ModuleIdentifier);637return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||638GUIDPreservedSymbols.count(VI.getGUID());639}640};641642struct IsPrevailing {643const DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy;644IsPrevailing(const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>645&PrevailingCopy)646: PrevailingCopy(PrevailingCopy) {}647648bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {649const auto &Prevailing = PrevailingCopy.find(GUID);650// Not in map means that there was only one copy, which must be prevailing.651if (Prevailing == PrevailingCopy.end())652return true;653return Prevailing->second == S;654};655};656} // namespace657658static void computeDeadSymbolsInIndex(659ModuleSummaryIndex &Index,660const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {661// We have no symbols resolution available. And can't do any better now in the662// case where the prevailing symbol is in a native object. It can be refined663// with linker information in the future.664auto isPrevailing = [&](GlobalValue::GUID G) {665return PrevailingType::Unknown;666};667computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,668/* ImportEnabled = */ true);669}670671/**672* Perform promotion and renaming of exported internal functions.673* Index is updated to reflect linkage changes from weak resolution.674*/675void ThinLTOCodeGenerator::promote(Module &TheModule, ModuleSummaryIndex &Index,676const lto::InputFile &File) {677auto ModuleCount = Index.modulePaths().size();678auto ModuleIdentifier = TheModule.getModuleIdentifier();679680// Collect for each module the list of function it defines (GUID -> Summary).681DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;682Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);683684// Convert the preserved symbols set from string to GUID685auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(686File, PreservedSymbols, Triple(TheModule.getTargetTriple()));687688// Add used symbol to the preserved symbols.689addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);690691// Compute "dead" symbols, we don't want to import/export these!692computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);693694// Compute prevailing symbols695DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;696computePrevailingCopies(Index, PrevailingCopy);697698// Generate import/export list699DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);700DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);701ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,702IsPrevailing(PrevailingCopy), ImportLists,703ExportLists);704705// Resolve prevailing symbols706StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;707resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,708PrevailingCopy);709710thinLTOFinalizeInModule(TheModule,711ModuleToDefinedGVSummaries[ModuleIdentifier],712/*PropagateAttrs=*/false);713714// Promote the exported values in the index, so that they are promoted715// in the module.716thinLTOInternalizeAndPromoteInIndex(717Index, IsExported(ExportLists, GUIDPreservedSymbols),718IsPrevailing(PrevailingCopy));719720// FIXME Set ClearDSOLocalOnDeclarations.721promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);722}723724/**725* Perform cross-module importing for the module identified by ModuleIdentifier.726*/727void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,728ModuleSummaryIndex &Index,729const lto::InputFile &File) {730auto ModuleMap = generateModuleMap(Modules);731auto ModuleCount = Index.modulePaths().size();732733// Collect for each module the list of function it defines (GUID -> Summary).734DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);735Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);736737// Convert the preserved symbols set from string to GUID738auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(739File, PreservedSymbols, Triple(TheModule.getTargetTriple()));740741addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);742743// Compute "dead" symbols, we don't want to import/export these!744computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);745746// Compute prevailing symbols747DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;748computePrevailingCopies(Index, PrevailingCopy);749750// Generate import/export list751DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);752DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);753ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,754IsPrevailing(PrevailingCopy), ImportLists,755ExportLists);756auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];757758// FIXME Set ClearDSOLocalOnDeclarations.759crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,760/*ClearDSOLocalOnDeclarations=*/false);761}762763/**764* Compute the list of summaries needed for importing into module.765*/766void ThinLTOCodeGenerator::gatherImportedSummariesForModule(767Module &TheModule, ModuleSummaryIndex &Index,768std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,769GVSummaryPtrSet &DecSummaries, const lto::InputFile &File) {770auto ModuleCount = Index.modulePaths().size();771auto ModuleIdentifier = TheModule.getModuleIdentifier();772773// Collect for each module the list of function it defines (GUID -> Summary).774DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);775Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);776777// Convert the preserved symbols set from string to GUID778auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(779File, PreservedSymbols, Triple(TheModule.getTargetTriple()));780781addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);782783// Compute "dead" symbols, we don't want to import/export these!784computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);785786// Compute prevailing symbols787DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;788computePrevailingCopies(Index, PrevailingCopy);789790// Generate import/export list791DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);792DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);793ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,794IsPrevailing(PrevailingCopy), ImportLists,795ExportLists);796797llvm::gatherImportedSummariesForModule(798ModuleIdentifier, ModuleToDefinedGVSummaries,799ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries);800}801802/**803* Emit the list of files needed for importing into module.804*/805void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName,806ModuleSummaryIndex &Index,807const lto::InputFile &File) {808auto ModuleCount = Index.modulePaths().size();809auto ModuleIdentifier = TheModule.getModuleIdentifier();810811// Collect for each module the list of function it defines (GUID -> Summary).812DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);813Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);814815// Convert the preserved symbols set from string to GUID816auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(817File, PreservedSymbols, Triple(TheModule.getTargetTriple()));818819addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);820821// Compute "dead" symbols, we don't want to import/export these!822computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);823824// Compute prevailing symbols825DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;826computePrevailingCopies(Index, PrevailingCopy);827828// Generate import/export list829DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);830DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);831ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,832IsPrevailing(PrevailingCopy), ImportLists,833ExportLists);834835// 'EmitImportsFiles' emits the list of modules from which to import from, and836// the set of keys in `ModuleToSummariesForIndex` should be a superset of keys837// in `DecSummaries`, so no need to use `DecSummaries` in `EmitImportFiles`.838GVSummaryPtrSet DecSummaries;839std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;840llvm::gatherImportedSummariesForModule(841ModuleIdentifier, ModuleToDefinedGVSummaries,842ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries);843844std::error_code EC;845if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,846ModuleToSummariesForIndex)))847report_fatal_error(Twine("Failed to open ") + OutputName +848" to save imports lists\n");849}850851/**852* Perform internalization. Runs promote and internalization together.853* Index is updated to reflect linkage changes.854*/855void ThinLTOCodeGenerator::internalize(Module &TheModule,856ModuleSummaryIndex &Index,857const lto::InputFile &File) {858initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));859auto ModuleCount = Index.modulePaths().size();860auto ModuleIdentifier = TheModule.getModuleIdentifier();861862// Convert the preserved symbols set from string to GUID863auto GUIDPreservedSymbols =864computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);865866addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);867868// Collect for each module the list of function it defines (GUID -> Summary).869DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);870Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);871872// Compute "dead" symbols, we don't want to import/export these!873computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);874875// Compute prevailing symbols876DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;877computePrevailingCopies(Index, PrevailingCopy);878879// Generate import/export list880DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);881DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);882ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,883IsPrevailing(PrevailingCopy), ImportLists,884ExportLists);885auto &ExportList = ExportLists[ModuleIdentifier];886887// Be friendly and don't nuke totally the module when the client didn't888// supply anything to preserve.889if (ExportList.empty() && GUIDPreservedSymbols.empty())890return;891892// Resolve prevailing symbols893StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;894resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,895PrevailingCopy);896897// Promote the exported values in the index, so that they are promoted898// in the module.899thinLTOInternalizeAndPromoteInIndex(900Index, IsExported(ExportLists, GUIDPreservedSymbols),901IsPrevailing(PrevailingCopy));902903// FIXME Set ClearDSOLocalOnDeclarations.904promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);905906// Internalization907thinLTOFinalizeInModule(TheModule,908ModuleToDefinedGVSummaries[ModuleIdentifier],909/*PropagateAttrs=*/false);910911thinLTOInternalizeModule(TheModule,912ModuleToDefinedGVSummaries[ModuleIdentifier]);913}914915/**916* Perform post-importing ThinLTO optimizations.917*/918void ThinLTOCodeGenerator::optimize(Module &TheModule) {919initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));920921// Optimize now922optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,923DebugPassManager, nullptr);924}925926/// Write out the generated object file, either from CacheEntryPath or from927/// OutputBuffer, preferring hard-link when possible.928/// Returns the path to the generated file in SavedObjectsDirectoryPath.929std::string930ThinLTOCodeGenerator::writeGeneratedObject(int count, StringRef CacheEntryPath,931const MemoryBuffer &OutputBuffer) {932auto ArchName = TMBuilder.TheTriple.getArchName();933SmallString<128> OutputPath(SavedObjectsDirectoryPath);934llvm::sys::path::append(OutputPath,935Twine(count) + "." + ArchName + ".thinlto.o");936OutputPath.c_str(); // Ensure the string is null terminated.937if (sys::fs::exists(OutputPath))938sys::fs::remove(OutputPath);939940// We don't return a memory buffer to the linker, just a list of files.941if (!CacheEntryPath.empty()) {942// Cache is enabled, hard-link the entry (or copy if hard-link fails).943auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);944if (!Err)945return std::string(OutputPath);946// Hard linking failed, try to copy.947Err = sys::fs::copy_file(CacheEntryPath, OutputPath);948if (!Err)949return std::string(OutputPath);950// Copy failed (could be because the CacheEntry was removed from the cache951// in the meantime by another process), fall back and try to write down the952// buffer to the output.953errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath954<< "' to '" << OutputPath << "'\n";955}956// No cache entry, just write out the buffer.957std::error_code Err;958raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);959if (Err)960report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");961OS << OutputBuffer.getBuffer();962return std::string(OutputPath);963}964965// Main entry point for the ThinLTO processing966void ThinLTOCodeGenerator::run() {967timeTraceProfilerBegin("ThinLink", StringRef(""));968auto TimeTraceScopeExit = llvm::make_scope_exit([]() {969if (llvm::timeTraceProfilerEnabled())970llvm::timeTraceProfilerEnd();971});972// Prepare the resulting object vector973assert(ProducedBinaries.empty() && "The generator should not be reused");974if (SavedObjectsDirectoryPath.empty())975ProducedBinaries.resize(Modules.size());976else {977sys::fs::create_directories(SavedObjectsDirectoryPath);978bool IsDir;979sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);980if (!IsDir)981report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");982ProducedBinaryFiles.resize(Modules.size());983}984985if (CodeGenOnly) {986// Perform only parallel codegen and return.987DefaultThreadPool Pool;988int count = 0;989for (auto &Mod : Modules) {990Pool.async([&](int count) {991LLVMContext Context;992Context.setDiscardValueNames(LTODiscardValueNames);993994// Parse module now995auto TheModule = loadModuleFromInput(Mod.get(), Context, false,996/*IsImporting*/ false);997998// CodeGen999auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());1000if (SavedObjectsDirectoryPath.empty())1001ProducedBinaries[count] = std::move(OutputBuffer);1002else1003ProducedBinaryFiles[count] =1004writeGeneratedObject(count, "", *OutputBuffer);1005}, count++);1006}10071008return;1009}10101011// Sequential linking phase1012auto Index = linkCombinedIndex();10131014// Save temps: index.1015if (!SaveTempsDir.empty()) {1016auto SaveTempPath = SaveTempsDir + "index.bc";1017std::error_code EC;1018raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);1019if (EC)1020report_fatal_error(Twine("Failed to open ") + SaveTempPath +1021" to save optimized bitcode\n");1022writeIndexToFile(*Index, OS);1023}102410251026// Prepare the module map.1027auto ModuleMap = generateModuleMap(Modules);1028auto ModuleCount = Modules.size();10291030// Collect for each module the list of function it defines (GUID -> Summary).1031DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);1032Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);10331034// Convert the preserved symbols set from string to GUID, this is needed for1035// computing the caching hash and the internalization.1036DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;1037for (const auto &M : Modules)1038computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,1039GUIDPreservedSymbols);10401041// Add used symbol from inputs to the preserved symbols.1042for (const auto &M : Modules)1043addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);10441045// Compute "dead" symbols, we don't want to import/export these!1046computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);10471048// Synthesize entry counts for functions in the combined index.1049computeSyntheticCounts(*Index);10501051// Currently there is no support for enabling whole program visibility via a1052// linker option in the old LTO API, but this call allows it to be specified1053// via the internal option. Must be done before WPD below.1054if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))1055Index->setWithWholeProgramVisibility();10561057// FIXME: This needs linker information via a TBD new interface1058updateVCallVisibilityInIndex(*Index,1059/*WholeProgramVisibilityEnabledInLTO=*/false,1060// FIXME: These need linker information via a1061// TBD new interface.1062/*DynamicExportSymbols=*/{},1063/*VisibleToRegularObjSymbols=*/{});10641065// Perform index-based WPD. This will return immediately if there are1066// no index entries in the typeIdMetadata map (e.g. if we are instead1067// performing IR-based WPD in hybrid regular/thin LTO mode).1068std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;1069std::set<GlobalValue::GUID> ExportedGUIDs;1070runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);1071for (auto GUID : ExportedGUIDs)1072GUIDPreservedSymbols.insert(GUID);10731074// Compute prevailing symbols1075DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;1076computePrevailingCopies(*Index, PrevailingCopy);10771078// Collect the import/export lists for all modules from the call-graph in the1079// combined index.1080DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists(ModuleCount);1081DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(ModuleCount);1082ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries,1083IsPrevailing(PrevailingCopy), ImportLists,1084ExportLists);10851086// We use a std::map here to be able to have a defined ordering when1087// producing a hash for the cache entry.1088// FIXME: we should be able to compute the caching hash for the entry based1089// on the index, and nuke this map.1090StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;10911092// Resolve prevailing symbols, this has to be computed early because it1093// impacts the caching.1094resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,1095PrevailingCopy);10961097// Use global summary-based analysis to identify symbols that can be1098// internalized (because they aren't exported or preserved as per callback).1099// Changes are made in the index, consumed in the ThinLTO backends.1100updateIndexWPDForExports(*Index,1101IsExported(ExportLists, GUIDPreservedSymbols),1102LocalWPDTargetsMap);1103thinLTOInternalizeAndPromoteInIndex(1104*Index, IsExported(ExportLists, GUIDPreservedSymbols),1105IsPrevailing(PrevailingCopy));11061107thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));11081109// Make sure that every module has an entry in the ExportLists, ImportList,1110// GVSummary and ResolvedODR maps to enable threaded access to these maps1111// below.1112for (auto &Module : Modules) {1113auto ModuleIdentifier = Module->getName();1114ExportLists[ModuleIdentifier];1115ImportLists[ModuleIdentifier];1116ResolvedODR[ModuleIdentifier];1117ModuleToDefinedGVSummaries[ModuleIdentifier];1118}11191120std::vector<BitcodeModule *> ModulesVec;1121ModulesVec.reserve(Modules.size());1122for (auto &Mod : Modules)1123ModulesVec.push_back(&Mod->getSingleBitcodeModule());1124std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);11251126if (llvm::timeTraceProfilerEnabled())1127llvm::timeTraceProfilerEnd();11281129TimeTraceScopeExit.release();11301131// Parallel optimizer + codegen1132{1133DefaultThreadPool Pool(heavyweight_hardware_concurrency(ThreadCount));1134for (auto IndexCount : ModulesOrdering) {1135auto &Mod = Modules[IndexCount];1136Pool.async([&](int count) {1137auto ModuleIdentifier = Mod->getName();1138auto &ExportList = ExportLists[ModuleIdentifier];11391140auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];11411142// The module may be cached, this helps handling it.1143ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,1144ImportLists[ModuleIdentifier], ExportList,1145ResolvedODR[ModuleIdentifier],1146DefinedGVSummaries, OptLevel, Freestanding,1147TMBuilder);1148auto CacheEntryPath = CacheEntry.getEntryPath();11491150{1151auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();1152LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")1153<< " '" << CacheEntryPath << "' for buffer "1154<< count << " " << ModuleIdentifier << "\n");11551156if (ErrOrBuffer) {1157// Cache Hit!1158if (SavedObjectsDirectoryPath.empty())1159ProducedBinaries[count] = std::move(ErrOrBuffer.get());1160else1161ProducedBinaryFiles[count] = writeGeneratedObject(1162count, CacheEntryPath, *ErrOrBuffer.get());1163return;1164}1165}11661167LLVMContext Context;1168Context.setDiscardValueNames(LTODiscardValueNames);1169Context.enableDebugTypeODRUniquing();1170auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(1171Context, RemarksFilename, RemarksPasses, RemarksFormat,1172RemarksWithHotness, RemarksHotnessThreshold, count);1173if (!DiagFileOrErr) {1174errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";1175report_fatal_error("ThinLTO: Can't get an output file for the "1176"remarks");1177}11781179// Parse module now1180auto TheModule = loadModuleFromInput(Mod.get(), Context, false,1181/*IsImporting*/ false);11821183// Save temps: original file.1184saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");11851186auto &ImportList = ImportLists[ModuleIdentifier];1187// Run the main process now, and generates a binary1188auto OutputBuffer = ProcessThinLTOModule(1189*TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,1190ExportList, GUIDPreservedSymbols,1191ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,1192DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,1193DebugPassManager);11941195// Commit to the cache (if enabled)1196CacheEntry.write(*OutputBuffer);11971198if (SavedObjectsDirectoryPath.empty()) {1199// We need to generated a memory buffer for the linker.1200if (!CacheEntryPath.empty()) {1201// When cache is enabled, reload from the cache if possible.1202// Releasing the buffer from the heap and reloading it from the1203// cache file with mmap helps us to lower memory pressure.1204// The freed memory can be used for the next input file.1205// The final binary link will read from the VFS cache (hopefully!)1206// or from disk (if the memory pressure was too high).1207auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();1208if (auto EC = ReloadedBufferOrErr.getError()) {1209// On error, keep the preexisting buffer and print a diagnostic.1210errs() << "remark: can't reload cached file '" << CacheEntryPath1211<< "': " << EC.message() << "\n";1212} else {1213OutputBuffer = std::move(*ReloadedBufferOrErr);1214}1215}1216ProducedBinaries[count] = std::move(OutputBuffer);1217return;1218}1219ProducedBinaryFiles[count] = writeGeneratedObject(1220count, CacheEntryPath, *OutputBuffer);1221}, IndexCount);1222}1223}12241225pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);12261227// If statistics were requested, print them out now.1228if (llvm::AreStatisticsEnabled())1229llvm::PrintStatistics();1230reportAndResetTimings();1231}123212331234