10b57cec5SDimitry Andric //===-LTO.cpp - LLVM Link Time Optimizer ----------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements functions and classes used to support LTO. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/LTO/LTO.h" 14349cc55cSDimitry Andric #include "llvm/ADT/ScopeExit.h" 15fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h" 160b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 17fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 185ffd83dbSDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 195ffd83dbSDimitry Andric #include "llvm/Analysis/StackSafetyAnalysis.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 210b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 220b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 230b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriter.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h" 250b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 260b57cec5SDimitry Andric #include "llvm/IR/AutoUpgrade.h" 270b57cec5SDimitry Andric #include "llvm/IR/DiagnosticPrinter.h" 280b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 295ffd83dbSDimitry Andric #include "llvm/IR/LLVMRemarkStreamer.h" 300b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 310b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 320b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 33*0fca6ea1SDimitry Andric #include "llvm/IR/RuntimeLibcalls.h" 340b57cec5SDimitry Andric #include "llvm/LTO/LTOBackend.h" 350b57cec5SDimitry Andric #include "llvm/LTO/SummaryBasedOptimizations.h" 360b57cec5SDimitry Andric #include "llvm/Linker/IRMover.h" 37349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 380b57cec5SDimitry Andric #include "llvm/Object/IRObjectFile.h" 39480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 400b57cec5SDimitry Andric #include "llvm/Support/Error.h" 41fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h" 420b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 430b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 440b57cec5SDimitry Andric #include "llvm/Support/Path.h" 450b57cec5SDimitry Andric #include "llvm/Support/SHA1.h" 460b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 470b57cec5SDimitry Andric #include "llvm/Support/ThreadPool.h" 480b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 495ffd83dbSDimitry Andric #include "llvm/Support/TimeProfiler.h" 501fd87a68SDimitry Andric #include "llvm/Support/ToolOutputFile.h" 510b57cec5SDimitry Andric #include "llvm/Support/VCSRevision.h" 520b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 530b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 540b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h" 5506c3fb27SDimitry Andric #include "llvm/Transforms/IPO/MemProfContextDisambiguation.h" 568bcb0991SDimitry Andric #include "llvm/Transforms/IPO/WholeProgramDevirt.h" 570b57cec5SDimitry Andric #include "llvm/Transforms/Utils/FunctionImportUtils.h" 580b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SplitModule.h" 590b57cec5SDimitry Andric 60bdd1243dSDimitry Andric #include <optional> 610b57cec5SDimitry Andric #include <set> 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric using namespace llvm; 640b57cec5SDimitry Andric using namespace lto; 650b57cec5SDimitry Andric using namespace object; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric #define DEBUG_TYPE "lto" 680b57cec5SDimitry Andric 69*0fca6ea1SDimitry Andric extern cl::opt<bool> UseNewDbgInfoFormat; 70*0fca6ea1SDimitry Andric 710b57cec5SDimitry Andric static cl::opt<bool> 720b57cec5SDimitry Andric DumpThinCGSCCs("dump-thin-cg-sccs", cl::init(false), cl::Hidden, 730b57cec5SDimitry Andric cl::desc("Dump the SCCs in the ThinLTO index's callgraph")); 740b57cec5SDimitry Andric 75bdd1243dSDimitry Andric namespace llvm { 760b57cec5SDimitry Andric /// Enable global value internalization in LTO. 770b57cec5SDimitry Andric cl::opt<bool> EnableLTOInternalization( 780b57cec5SDimitry Andric "enable-lto-internalization", cl::init(true), cl::Hidden, 790b57cec5SDimitry Andric cl::desc("Enable global value internalization in LTO")); 800b57cec5SDimitry Andric 8106c3fb27SDimitry Andric /// Indicate we are linking with an allocator that supports hot/cold operator 8206c3fb27SDimitry Andric /// new interfaces. 8306c3fb27SDimitry Andric extern cl::opt<bool> SupportsHotColdNew; 8406c3fb27SDimitry Andric 8506c3fb27SDimitry Andric /// Enable MemProf context disambiguation for thin link. 8606c3fb27SDimitry Andric extern cl::opt<bool> EnableMemProfContextDisambiguation; 875f757f3fSDimitry Andric } // namespace llvm 8806c3fb27SDimitry Andric 890b57cec5SDimitry Andric // Computes a unique hash for the Module considering the current list of 900b57cec5SDimitry Andric // export/import and other global analysis results. 910b57cec5SDimitry Andric // The hash is produced in \p Key. 920b57cec5SDimitry Andric void llvm::computeLTOCacheKey( 930b57cec5SDimitry Andric SmallString<40> &Key, const Config &Conf, const ModuleSummaryIndex &Index, 940b57cec5SDimitry Andric StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList, 950b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 960b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 970b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals, 980b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDefs, 990b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDecls) { 1000b57cec5SDimitry Andric // Compute the unique hash for this entry. 1010b57cec5SDimitry Andric // This is based on the current compiler version, the module itself, the 1020b57cec5SDimitry Andric // export list, the hash for every single module in the import list, the 1030b57cec5SDimitry Andric // list of ResolvedODR for the module, and the list of preserved symbols. 1040b57cec5SDimitry Andric SHA1 Hasher; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Start with the compiler revision 1070b57cec5SDimitry Andric Hasher.update(LLVM_VERSION_STRING); 1080b57cec5SDimitry Andric #ifdef LLVM_REVISION 1090b57cec5SDimitry Andric Hasher.update(LLVM_REVISION); 1100b57cec5SDimitry Andric #endif 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // Include the parts of the LTO configuration that affect code generation. 1130b57cec5SDimitry Andric auto AddString = [&](StringRef Str) { 1140b57cec5SDimitry Andric Hasher.update(Str); 1150b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>{0}); 1160b57cec5SDimitry Andric }; 1170b57cec5SDimitry Andric auto AddUnsigned = [&](unsigned I) { 1180b57cec5SDimitry Andric uint8_t Data[4]; 1195ffd83dbSDimitry Andric support::endian::write32le(Data, I); 120*0fca6ea1SDimitry Andric Hasher.update(Data); 1210b57cec5SDimitry Andric }; 1220b57cec5SDimitry Andric auto AddUint64 = [&](uint64_t I) { 1230b57cec5SDimitry Andric uint8_t Data[8]; 1245ffd83dbSDimitry Andric support::endian::write64le(Data, I); 125*0fca6ea1SDimitry Andric Hasher.update(Data); 126*0fca6ea1SDimitry Andric }; 127*0fca6ea1SDimitry Andric auto AddUint8 = [&](const uint8_t I) { 128*0fca6ea1SDimitry Andric Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&I, 1)); 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric AddString(Conf.CPU); 1310b57cec5SDimitry Andric // FIXME: Hash more of Options. For now all clients initialize Options from 1320b57cec5SDimitry Andric // command-line flags (which is unsupported in production), but may set 133*0fca6ea1SDimitry Andric // X86RelaxRelocations. The clang driver can also pass FunctionSections, 1340b57cec5SDimitry Andric // DataSections and DebuggerTuning via command line flags. 135*0fca6ea1SDimitry Andric AddUnsigned(Conf.Options.MCOptions.X86RelaxRelocations); 1360b57cec5SDimitry Andric AddUnsigned(Conf.Options.FunctionSections); 1370b57cec5SDimitry Andric AddUnsigned(Conf.Options.DataSections); 1380b57cec5SDimitry Andric AddUnsigned((unsigned)Conf.Options.DebuggerTuning); 1390b57cec5SDimitry Andric for (auto &A : Conf.MAttrs) 1400b57cec5SDimitry Andric AddString(A); 1410b57cec5SDimitry Andric if (Conf.RelocModel) 1420b57cec5SDimitry Andric AddUnsigned(*Conf.RelocModel); 1430b57cec5SDimitry Andric else 1440b57cec5SDimitry Andric AddUnsigned(-1); 1450b57cec5SDimitry Andric if (Conf.CodeModel) 1460b57cec5SDimitry Andric AddUnsigned(*Conf.CodeModel); 1470b57cec5SDimitry Andric else 1480b57cec5SDimitry Andric AddUnsigned(-1); 149bdd1243dSDimitry Andric for (const auto &S : Conf.MllvmArgs) 150bdd1243dSDimitry Andric AddString(S); 1515f757f3fSDimitry Andric AddUnsigned(static_cast<int>(Conf.CGOptLevel)); 1525f757f3fSDimitry Andric AddUnsigned(static_cast<int>(Conf.CGFileType)); 1530b57cec5SDimitry Andric AddUnsigned(Conf.OptLevel); 1540b57cec5SDimitry Andric AddUnsigned(Conf.Freestanding); 1550b57cec5SDimitry Andric AddString(Conf.OptPipeline); 1560b57cec5SDimitry Andric AddString(Conf.AAPipeline); 1570b57cec5SDimitry Andric AddString(Conf.OverrideTriple); 1580b57cec5SDimitry Andric AddString(Conf.DefaultTriple); 1590b57cec5SDimitry Andric AddString(Conf.DwoDir); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric // Include the hash for the current module 1620b57cec5SDimitry Andric auto ModHash = Index.getModuleHash(ModuleID); 1630b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash))); 1640946e70aSDimitry Andric 165*0fca6ea1SDimitry Andric // TODO: `ExportList` is determined by `ImportList`. Since `ImportList` is 166*0fca6ea1SDimitry Andric // used to compute cache key, we could omit hashing `ExportList` here. 1670946e70aSDimitry Andric std::vector<uint64_t> ExportsGUID; 1680946e70aSDimitry Andric ExportsGUID.reserve(ExportList.size()); 169*0fca6ea1SDimitry Andric for (const auto &VI : ExportList) 170*0fca6ea1SDimitry Andric ExportsGUID.push_back(VI.getGUID()); 1710946e70aSDimitry Andric 1720946e70aSDimitry Andric // Sort the export list elements GUIDs. 1730946e70aSDimitry Andric llvm::sort(ExportsGUID); 174*0fca6ea1SDimitry Andric for (auto GUID : ExportsGUID) 175480093f4SDimitry Andric Hasher.update(ArrayRef<uint8_t>((uint8_t *)&GUID, sizeof(GUID))); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric // Include the hash for every module we import functions from. The set of 1780b57cec5SDimitry Andric // imported symbols for each module may affect code generation and is 1790b57cec5SDimitry Andric // sensitive to link order, so include that as well. 1800946e70aSDimitry Andric using ImportMapIteratorTy = FunctionImporter::ImportMapTy::const_iterator; 18106c3fb27SDimitry Andric struct ImportModule { 18206c3fb27SDimitry Andric ImportMapIteratorTy ModIt; 18306c3fb27SDimitry Andric const ModuleSummaryIndex::ModuleInfo *ModInfo; 18406c3fb27SDimitry Andric 1855f757f3fSDimitry Andric StringRef getIdentifier() const { return ModIt->getFirst(); } 18606c3fb27SDimitry Andric const FunctionImporter::FunctionsToImportTy &getFunctions() const { 18706c3fb27SDimitry Andric return ModIt->second; 18806c3fb27SDimitry Andric } 18906c3fb27SDimitry Andric 1905f757f3fSDimitry Andric const ModuleHash &getHash() const { return ModInfo->second; } 19106c3fb27SDimitry Andric }; 19206c3fb27SDimitry Andric 19306c3fb27SDimitry Andric std::vector<ImportModule> ImportModulesVector; 1940946e70aSDimitry Andric ImportModulesVector.reserve(ImportList.size()); 1950946e70aSDimitry Andric 1960946e70aSDimitry Andric for (ImportMapIteratorTy It = ImportList.begin(); It != ImportList.end(); 1970946e70aSDimitry Andric ++It) { 1985f757f3fSDimitry Andric ImportModulesVector.push_back({It, Index.getModule(It->getFirst())}); 1990946e70aSDimitry Andric } 2008a4dda33SDimitry Andric // Order using module hash, to be both independent of module name and 2018a4dda33SDimitry Andric // module order. 2020946e70aSDimitry Andric llvm::sort(ImportModulesVector, 20306c3fb27SDimitry Andric [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { 2048a4dda33SDimitry Andric return Lhs.getHash() < Rhs.getHash(); 20506c3fb27SDimitry Andric }); 206*0fca6ea1SDimitry Andric std::vector<std::pair<uint64_t, uint8_t>> ImportedGUIDs; 20706c3fb27SDimitry Andric for (const ImportModule &Entry : ImportModulesVector) { 20806c3fb27SDimitry Andric auto ModHash = Entry.getHash(); 2090b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash))); 2100b57cec5SDimitry Andric 21106c3fb27SDimitry Andric AddUint64(Entry.getFunctions().size()); 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric ImportedGUIDs.clear(); 214*0fca6ea1SDimitry Andric for (auto &[Fn, ImportType] : Entry.getFunctions()) 215*0fca6ea1SDimitry Andric ImportedGUIDs.push_back(std::make_pair(Fn, ImportType)); 216*0fca6ea1SDimitry Andric llvm::sort(ImportedGUIDs); 217*0fca6ea1SDimitry Andric for (auto &[GUID, Type] : ImportedGUIDs) { 218*0fca6ea1SDimitry Andric AddUint64(GUID); 219*0fca6ea1SDimitry Andric AddUint8(Type); 220*0fca6ea1SDimitry Andric } 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric // Include the hash for the resolved ODR. 2240b57cec5SDimitry Andric for (auto &Entry : ResolvedODR) { 2250b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&Entry.first, 2260b57cec5SDimitry Andric sizeof(GlobalValue::GUID))); 2270b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&Entry.second, 2280b57cec5SDimitry Andric sizeof(GlobalValue::LinkageTypes))); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric // Members of CfiFunctionDefs and CfiFunctionDecls that are referenced or 2320b57cec5SDimitry Andric // defined in this module. 2330b57cec5SDimitry Andric std::set<GlobalValue::GUID> UsedCfiDefs; 2340b57cec5SDimitry Andric std::set<GlobalValue::GUID> UsedCfiDecls; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Typeids used in this module. 2370b57cec5SDimitry Andric std::set<GlobalValue::GUID> UsedTypeIds; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric auto AddUsedCfiGlobal = [&](GlobalValue::GUID ValueGUID) { 2400b57cec5SDimitry Andric if (CfiFunctionDefs.count(ValueGUID)) 2410b57cec5SDimitry Andric UsedCfiDefs.insert(ValueGUID); 2420b57cec5SDimitry Andric if (CfiFunctionDecls.count(ValueGUID)) 2430b57cec5SDimitry Andric UsedCfiDecls.insert(ValueGUID); 2440b57cec5SDimitry Andric }; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric auto AddUsedThings = [&](GlobalValueSummary *GS) { 2470b57cec5SDimitry Andric if (!GS) return; 248fe6060f1SDimitry Andric AddUnsigned(GS->getVisibility()); 2490b57cec5SDimitry Andric AddUnsigned(GS->isLive()); 2500b57cec5SDimitry Andric AddUnsigned(GS->canAutoHide()); 2510b57cec5SDimitry Andric for (const ValueInfo &VI : GS->refs()) { 252fe6060f1SDimitry Andric AddUnsigned(VI.isDSOLocal(Index.withDSOLocalPropagation())); 2530b57cec5SDimitry Andric AddUsedCfiGlobal(VI.getGUID()); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric if (auto *GVS = dyn_cast<GlobalVarSummary>(GS)) { 2560b57cec5SDimitry Andric AddUnsigned(GVS->maybeReadOnly()); 2570b57cec5SDimitry Andric AddUnsigned(GVS->maybeWriteOnly()); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric if (auto *FS = dyn_cast<FunctionSummary>(GS)) { 2600b57cec5SDimitry Andric for (auto &TT : FS->type_tests()) 2610b57cec5SDimitry Andric UsedTypeIds.insert(TT); 2620b57cec5SDimitry Andric for (auto &TT : FS->type_test_assume_vcalls()) 2630b57cec5SDimitry Andric UsedTypeIds.insert(TT.GUID); 2640b57cec5SDimitry Andric for (auto &TT : FS->type_checked_load_vcalls()) 2650b57cec5SDimitry Andric UsedTypeIds.insert(TT.GUID); 2660b57cec5SDimitry Andric for (auto &TT : FS->type_test_assume_const_vcalls()) 2670b57cec5SDimitry Andric UsedTypeIds.insert(TT.VFunc.GUID); 2680b57cec5SDimitry Andric for (auto &TT : FS->type_checked_load_const_vcalls()) 2690b57cec5SDimitry Andric UsedTypeIds.insert(TT.VFunc.GUID); 2700b57cec5SDimitry Andric for (auto &ET : FS->calls()) { 271fe6060f1SDimitry Andric AddUnsigned(ET.first.isDSOLocal(Index.withDSOLocalPropagation())); 2720b57cec5SDimitry Andric AddUsedCfiGlobal(ET.first.getGUID()); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric }; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // Include the hash for the linkage type to reflect internalization and weak 2780b57cec5SDimitry Andric // resolution, and collect any used type identifier resolutions. 2790b57cec5SDimitry Andric for (auto &GS : DefinedGlobals) { 2800b57cec5SDimitry Andric GlobalValue::LinkageTypes Linkage = GS.second->linkage(); 2810b57cec5SDimitry Andric Hasher.update( 2820b57cec5SDimitry Andric ArrayRef<uint8_t>((const uint8_t *)&Linkage, sizeof(Linkage))); 2830b57cec5SDimitry Andric AddUsedCfiGlobal(GS.first); 2840b57cec5SDimitry Andric AddUsedThings(GS.second); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric // Imported functions may introduce new uses of type identifier resolutions, 2880b57cec5SDimitry Andric // so we need to collect their used resolutions as well. 28906c3fb27SDimitry Andric for (const ImportModule &ImpM : ImportModulesVector) 290*0fca6ea1SDimitry Andric for (auto &[GUID, UnusedImportType] : ImpM.getFunctions()) { 29106c3fb27SDimitry Andric GlobalValueSummary *S = 292*0fca6ea1SDimitry Andric Index.findSummaryInModule(GUID, ImpM.getIdentifier()); 2930b57cec5SDimitry Andric AddUsedThings(S); 2940b57cec5SDimitry Andric // If this is an alias, we also care about any types/etc. that the aliasee 2950b57cec5SDimitry Andric // may reference. 2960b57cec5SDimitry Andric if (auto *AS = dyn_cast_or_null<AliasSummary>(S)) 2970b57cec5SDimitry Andric AddUsedThings(AS->getBaseObject()); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric auto AddTypeIdSummary = [&](StringRef TId, const TypeIdSummary &S) { 3010b57cec5SDimitry Andric AddString(TId); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric AddUnsigned(S.TTRes.TheKind); 3040b57cec5SDimitry Andric AddUnsigned(S.TTRes.SizeM1BitWidth); 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric AddUint64(S.TTRes.AlignLog2); 3070b57cec5SDimitry Andric AddUint64(S.TTRes.SizeM1); 3080b57cec5SDimitry Andric AddUint64(S.TTRes.BitMask); 3090b57cec5SDimitry Andric AddUint64(S.TTRes.InlineBits); 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric AddUint64(S.WPDRes.size()); 3120b57cec5SDimitry Andric for (auto &WPD : S.WPDRes) { 3130b57cec5SDimitry Andric AddUnsigned(WPD.first); 3140b57cec5SDimitry Andric AddUnsigned(WPD.second.TheKind); 3150b57cec5SDimitry Andric AddString(WPD.second.SingleImplName); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric AddUint64(WPD.second.ResByArg.size()); 3180b57cec5SDimitry Andric for (auto &ByArg : WPD.second.ResByArg) { 3190b57cec5SDimitry Andric AddUint64(ByArg.first.size()); 3200b57cec5SDimitry Andric for (uint64_t Arg : ByArg.first) 3210b57cec5SDimitry Andric AddUint64(Arg); 3220b57cec5SDimitry Andric AddUnsigned(ByArg.second.TheKind); 3230b57cec5SDimitry Andric AddUint64(ByArg.second.Info); 3240b57cec5SDimitry Andric AddUnsigned(ByArg.second.Byte); 3250b57cec5SDimitry Andric AddUnsigned(ByArg.second.Bit); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric }; 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Include the hash for all type identifiers used by this module. 3310b57cec5SDimitry Andric for (GlobalValue::GUID TId : UsedTypeIds) { 3320b57cec5SDimitry Andric auto TidIter = Index.typeIds().equal_range(TId); 3330b57cec5SDimitry Andric for (auto It = TidIter.first; It != TidIter.second; ++It) 3340b57cec5SDimitry Andric AddTypeIdSummary(It->second.first, It->second.second); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric AddUnsigned(UsedCfiDefs.size()); 3380b57cec5SDimitry Andric for (auto &V : UsedCfiDefs) 3390b57cec5SDimitry Andric AddUint64(V); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric AddUnsigned(UsedCfiDecls.size()); 3420b57cec5SDimitry Andric for (auto &V : UsedCfiDecls) 3430b57cec5SDimitry Andric AddUint64(V); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric if (!Conf.SampleProfile.empty()) { 3460b57cec5SDimitry Andric auto FileOrErr = MemoryBuffer::getFile(Conf.SampleProfile); 3470b57cec5SDimitry Andric if (FileOrErr) { 3480b57cec5SDimitry Andric Hasher.update(FileOrErr.get()->getBuffer()); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric if (!Conf.ProfileRemapping.empty()) { 3510b57cec5SDimitry Andric FileOrErr = MemoryBuffer::getFile(Conf.ProfileRemapping); 3520b57cec5SDimitry Andric if (FileOrErr) 3530b57cec5SDimitry Andric Hasher.update(FileOrErr.get()->getBuffer()); 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric Key = toHex(Hasher.result()); 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric static void thinLTOResolvePrevailingGUID( 362fe6060f1SDimitry Andric const Config &C, ValueInfo VI, 363fe6060f1SDimitry Andric DenseSet<GlobalValueSummary *> &GlobalInvolvedWithAlias, 3640b57cec5SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 3650b57cec5SDimitry Andric isPrevailing, 3660b57cec5SDimitry Andric function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> 3670b57cec5SDimitry Andric recordNewLinkage, 3680b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) { 369fe6060f1SDimitry Andric GlobalValue::VisibilityTypes Visibility = 370fe6060f1SDimitry Andric C.VisibilityScheme == Config::ELF ? VI.getELFVisibility() 371fe6060f1SDimitry Andric : GlobalValue::DefaultVisibility; 3720b57cec5SDimitry Andric for (auto &S : VI.getSummaryList()) { 3730b57cec5SDimitry Andric GlobalValue::LinkageTypes OriginalLinkage = S->linkage(); 3740b57cec5SDimitry Andric // Ignore local and appending linkage values since the linker 3750b57cec5SDimitry Andric // doesn't resolve them. 3760b57cec5SDimitry Andric if (GlobalValue::isLocalLinkage(OriginalLinkage) || 3770b57cec5SDimitry Andric GlobalValue::isAppendingLinkage(S->linkage())) 3780b57cec5SDimitry Andric continue; 3790b57cec5SDimitry Andric // We need to emit only one of these. The prevailing module will keep it, 3800b57cec5SDimitry Andric // but turned into a weak, while the others will drop it when possible. 3810b57cec5SDimitry Andric // This is both a compile-time optimization and a correctness 3820b57cec5SDimitry Andric // transformation. This is necessary for correctness when we have exported 3830b57cec5SDimitry Andric // a reference - we need to convert the linkonce to weak to 3840b57cec5SDimitry Andric // ensure a copy is kept to satisfy the exported reference. 3850b57cec5SDimitry Andric // FIXME: We may want to split the compile time and correctness 3860b57cec5SDimitry Andric // aspects into separate routines. 3870b57cec5SDimitry Andric if (isPrevailing(VI.getGUID(), S.get())) { 3880b57cec5SDimitry Andric if (GlobalValue::isLinkOnceLinkage(OriginalLinkage)) { 3890b57cec5SDimitry Andric S->setLinkage(GlobalValue::getWeakLinkage( 3900b57cec5SDimitry Andric GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))); 3910b57cec5SDimitry Andric // The kept copy is eligible for auto-hiding (hidden visibility) if all 3920b57cec5SDimitry Andric // copies were (i.e. they were all linkonce_odr global unnamed addr). 3930b57cec5SDimitry Andric // If any copy is not (e.g. it was originally weak_odr), then the symbol 3940b57cec5SDimitry Andric // must remain externally available (e.g. a weak_odr from an explicitly 3950b57cec5SDimitry Andric // instantiated template). Additionally, if it is in the 3960b57cec5SDimitry Andric // GUIDPreservedSymbols set, that means that it is visibile outside 3970b57cec5SDimitry Andric // the summary (e.g. in a native object or a bitcode file without 3980b57cec5SDimitry Andric // summary), and in that case we cannot hide it as it isn't possible to 3990b57cec5SDimitry Andric // check all copies. 4000b57cec5SDimitry Andric S->setCanAutoHide(VI.canAutoHide() && 4010b57cec5SDimitry Andric !GUIDPreservedSymbols.count(VI.getGUID())); 4020b57cec5SDimitry Andric } 403fe6060f1SDimitry Andric if (C.VisibilityScheme == Config::FromPrevailing) 404fe6060f1SDimitry Andric Visibility = S->getVisibility(); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric // Alias and aliasee can't be turned into available_externally. 4070b57cec5SDimitry Andric else if (!isa<AliasSummary>(S.get()) && 4080b57cec5SDimitry Andric !GlobalInvolvedWithAlias.count(S.get())) 4090b57cec5SDimitry Andric S->setLinkage(GlobalValue::AvailableExternallyLinkage); 410fe6060f1SDimitry Andric 411fe6060f1SDimitry Andric // For ELF, set visibility to the computed visibility from summaries. We 412fe6060f1SDimitry Andric // don't track visibility from declarations so this may be more relaxed than 413fe6060f1SDimitry Andric // the most constraining one. 414fe6060f1SDimitry Andric if (C.VisibilityScheme == Config::ELF) 415fe6060f1SDimitry Andric S->setVisibility(Visibility); 416fe6060f1SDimitry Andric 4170b57cec5SDimitry Andric if (S->linkage() != OriginalLinkage) 4180b57cec5SDimitry Andric recordNewLinkage(S->modulePath(), VI.getGUID(), S->linkage()); 4190b57cec5SDimitry Andric } 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric if (C.VisibilityScheme == Config::FromPrevailing) { 422fe6060f1SDimitry Andric for (auto &S : VI.getSummaryList()) { 423fe6060f1SDimitry Andric GlobalValue::LinkageTypes OriginalLinkage = S->linkage(); 424fe6060f1SDimitry Andric if (GlobalValue::isLocalLinkage(OriginalLinkage) || 425fe6060f1SDimitry Andric GlobalValue::isAppendingLinkage(S->linkage())) 426fe6060f1SDimitry Andric continue; 427fe6060f1SDimitry Andric S->setVisibility(Visibility); 428fe6060f1SDimitry Andric } 429fe6060f1SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric /// Resolve linkage for prevailing symbols in the \p Index. 4330b57cec5SDimitry Andric // 4340b57cec5SDimitry Andric // We'd like to drop these functions if they are no longer referenced in the 4350b57cec5SDimitry Andric // current module. However there is a chance that another module is still 4360b57cec5SDimitry Andric // referencing them because of the import. We make sure we always emit at least 4370b57cec5SDimitry Andric // one copy. 4380b57cec5SDimitry Andric void llvm::thinLTOResolvePrevailingInIndex( 439fe6060f1SDimitry Andric const Config &C, ModuleSummaryIndex &Index, 4400b57cec5SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 4410b57cec5SDimitry Andric isPrevailing, 4420b57cec5SDimitry Andric function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> 4430b57cec5SDimitry Andric recordNewLinkage, 4440b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) { 4450b57cec5SDimitry Andric // We won't optimize the globals that are referenced by an alias for now 4460b57cec5SDimitry Andric // Ideally we should turn the alias into a global and duplicate the definition 4470b57cec5SDimitry Andric // when needed. 4480b57cec5SDimitry Andric DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias; 4490b57cec5SDimitry Andric for (auto &I : Index) 4500b57cec5SDimitry Andric for (auto &S : I.second.SummaryList) 4510b57cec5SDimitry Andric if (auto AS = dyn_cast<AliasSummary>(S.get())) 4520b57cec5SDimitry Andric GlobalInvolvedWithAlias.insert(&AS->getAliasee()); 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric for (auto &I : Index) 455fe6060f1SDimitry Andric thinLTOResolvePrevailingGUID(C, Index.getValueInfo(I), 456fe6060f1SDimitry Andric GlobalInvolvedWithAlias, isPrevailing, 457fe6060f1SDimitry Andric recordNewLinkage, GUIDPreservedSymbols); 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric static void thinLTOInternalizeAndPromoteGUID( 461480093f4SDimitry Andric ValueInfo VI, function_ref<bool(StringRef, ValueInfo)> isExported, 4628bcb0991SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 4638bcb0991SDimitry Andric isPrevailing) { 46406c3fb27SDimitry Andric auto ExternallyVisibleCopies = 46506c3fb27SDimitry Andric llvm::count_if(VI.getSummaryList(), 46606c3fb27SDimitry Andric [](const std::unique_ptr<GlobalValueSummary> &Summary) { 46706c3fb27SDimitry Andric return !GlobalValue::isLocalLinkage(Summary->linkage()); 46806c3fb27SDimitry Andric }); 46906c3fb27SDimitry Andric 470480093f4SDimitry Andric for (auto &S : VI.getSummaryList()) { 47106c3fb27SDimitry Andric // First see if we need to promote an internal value because it is not 47206c3fb27SDimitry Andric // exported. 473480093f4SDimitry Andric if (isExported(S->modulePath(), VI)) { 4740b57cec5SDimitry Andric if (GlobalValue::isLocalLinkage(S->linkage())) 4750b57cec5SDimitry Andric S->setLinkage(GlobalValue::ExternalLinkage); 47606c3fb27SDimitry Andric continue; 47706c3fb27SDimitry Andric } 47806c3fb27SDimitry Andric 47906c3fb27SDimitry Andric // Otherwise, see if we can internalize. 48006c3fb27SDimitry Andric if (!EnableLTOInternalization) 48106c3fb27SDimitry Andric continue; 48206c3fb27SDimitry Andric 4835f757f3fSDimitry Andric // Non-exported values with external linkage can be internalized. 4845f757f3fSDimitry Andric if (GlobalValue::isExternalLinkage(S->linkage())) { 4855f757f3fSDimitry Andric S->setLinkage(GlobalValue::InternalLinkage); 48606c3fb27SDimitry Andric continue; 4875f757f3fSDimitry Andric } 48806c3fb27SDimitry Andric 4895f757f3fSDimitry Andric // Non-exported function and variable definitions with a weak-for-linker 49006c3fb27SDimitry Andric // linkage can be internalized in certain cases. The minimum legality 49106c3fb27SDimitry Andric // requirements would be that they are not address taken to ensure that we 49206c3fb27SDimitry Andric // don't break pointer equality checks, and that variables are either read- 49306c3fb27SDimitry Andric // or write-only. For functions, this is the case if either all copies are 49406c3fb27SDimitry Andric // [local_]unnamed_addr, or we can propagate reference edge attributes 49506c3fb27SDimitry Andric // (which is how this is guaranteed for variables, when analyzing whether 49606c3fb27SDimitry Andric // they are read or write-only). 49706c3fb27SDimitry Andric // 4985f757f3fSDimitry Andric // However, we only get to this code for weak-for-linkage values in one of 49906c3fb27SDimitry Andric // two cases: 50006c3fb27SDimitry Andric // 1) The prevailing copy is not in IR (it is in native code). 50106c3fb27SDimitry Andric // 2) The prevailing copy in IR is not exported from its module. 50206c3fb27SDimitry Andric // Additionally, at least for the new LTO API, case 2 will only happen if 50306c3fb27SDimitry Andric // there is exactly one definition of the value (i.e. in exactly one 50406c3fb27SDimitry Andric // module), as duplicate defs are result in the value being marked exported. 50506c3fb27SDimitry Andric // Likely, users of the legacy LTO API are similar, however, currently there 50606c3fb27SDimitry Andric // are llvm-lto based tests of the legacy LTO API that do not mark 50706c3fb27SDimitry Andric // duplicate linkonce_odr copies as exported via the tool, so we need 50806c3fb27SDimitry Andric // to handle that case below by checking the number of copies. 50906c3fb27SDimitry Andric // 5105f757f3fSDimitry Andric // Generally, we only want to internalize a weak-for-linker value in case 51106c3fb27SDimitry Andric // 2, because in case 1 we cannot see how the value is used to know if it 51206c3fb27SDimitry Andric // is read or write-only. We also don't want to bloat the binary with 5135f757f3fSDimitry Andric // multiple internalized copies of non-prevailing linkonce/weak functions. 51406c3fb27SDimitry Andric // Note if we don't internalize, we will convert non-prevailing copies to 51506c3fb27SDimitry Andric // available_externally anyway, so that we drop them after inlining. The 51606c3fb27SDimitry Andric // only reason to internalize such a function is if we indeed have a single 51706c3fb27SDimitry Andric // copy, because internalizing it won't increase binary size, and enables 51806c3fb27SDimitry Andric // use of inliner heuristics that are more aggressive in the face of a 51906c3fb27SDimitry Andric // single call to a static (local). For variables, internalizing a read or 52006c3fb27SDimitry Andric // write only variable can enable more aggressive optimization. However, we 52106c3fb27SDimitry Andric // already perform this elsewhere in the ThinLTO backend handling for 52206c3fb27SDimitry Andric // read or write-only variables (processGlobalForThinLTO). 52306c3fb27SDimitry Andric // 5245f757f3fSDimitry Andric // Therefore, only internalize linkonce/weak if there is a single copy, that 5255f757f3fSDimitry Andric // is prevailing in this IR module. We can do so aggressively, without 52606c3fb27SDimitry Andric // requiring the address to be insignificant, or that a variable be read or 52706c3fb27SDimitry Andric // write-only. 5285f757f3fSDimitry Andric if (!GlobalValue::isWeakForLinker(S->linkage()) || 5295f757f3fSDimitry Andric GlobalValue::isExternalWeakLinkage(S->linkage())) 53006c3fb27SDimitry Andric continue; 53106c3fb27SDimitry Andric 5325f757f3fSDimitry Andric if (isPrevailing(VI.getGUID(), S.get()) && ExternallyVisibleCopies == 1) 5330b57cec5SDimitry Andric S->setLinkage(GlobalValue::InternalLinkage); 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric // Update the linkages in the given \p Index to mark exported values 5380b57cec5SDimitry Andric // as external and non-exported values as internal. 5390b57cec5SDimitry Andric void llvm::thinLTOInternalizeAndPromoteInIndex( 5400b57cec5SDimitry Andric ModuleSummaryIndex &Index, 541480093f4SDimitry Andric function_ref<bool(StringRef, ValueInfo)> isExported, 5428bcb0991SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 5438bcb0991SDimitry Andric isPrevailing) { 5440b57cec5SDimitry Andric for (auto &I : Index) 545480093f4SDimitry Andric thinLTOInternalizeAndPromoteGUID(Index.getValueInfo(I), isExported, 5468bcb0991SDimitry Andric isPrevailing); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // Requires a destructor for std::vector<InputModule>. 5500b57cec5SDimitry Andric InputFile::~InputFile() = default; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) { 5530b57cec5SDimitry Andric std::unique_ptr<InputFile> File(new InputFile); 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric Expected<IRSymtabFile> FOrErr = readIRSymtab(Object); 5560b57cec5SDimitry Andric if (!FOrErr) 5570b57cec5SDimitry Andric return FOrErr.takeError(); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric File->TargetTriple = FOrErr->TheReader.getTargetTriple(); 5600b57cec5SDimitry Andric File->SourceFileName = FOrErr->TheReader.getSourceFileName(); 5610b57cec5SDimitry Andric File->COFFLinkerOpts = FOrErr->TheReader.getCOFFLinkerOpts(); 5620b57cec5SDimitry Andric File->DependentLibraries = FOrErr->TheReader.getDependentLibraries(); 5630b57cec5SDimitry Andric File->ComdatTable = FOrErr->TheReader.getComdatTable(); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric for (unsigned I = 0; I != FOrErr->Mods.size(); ++I) { 5660b57cec5SDimitry Andric size_t Begin = File->Symbols.size(); 5670b57cec5SDimitry Andric for (const irsymtab::Reader::SymbolRef &Sym : 5680b57cec5SDimitry Andric FOrErr->TheReader.module_symbols(I)) 5690b57cec5SDimitry Andric // Skip symbols that are irrelevant to LTO. Note that this condition needs 5700b57cec5SDimitry Andric // to match the one in Skip() in LTO::addRegularLTO(). 5710b57cec5SDimitry Andric if (Sym.isGlobal() && !Sym.isFormatSpecific()) 5720b57cec5SDimitry Andric File->Symbols.push_back(Sym); 5730b57cec5SDimitry Andric File->ModuleSymIndices.push_back({Begin, File->Symbols.size()}); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric File->Mods = FOrErr->Mods; 5770b57cec5SDimitry Andric File->Strtab = std::move(FOrErr->Strtab); 5780b57cec5SDimitry Andric return std::move(File); 5790b57cec5SDimitry Andric } 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric StringRef InputFile::getName() const { 5820b57cec5SDimitry Andric return Mods[0].getModuleIdentifier(); 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric BitcodeModule &InputFile::getSingleBitcodeModule() { 5860b57cec5SDimitry Andric assert(Mods.size() == 1 && "Expect only one bitcode module"); 5870b57cec5SDimitry Andric return Mods[0]; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel, 591480093f4SDimitry Andric const Config &Conf) 5920b57cec5SDimitry Andric : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel), 5938bcb0991SDimitry Andric Ctx(Conf), CombinedModule(std::make_unique<Module>("ld-temp.o", Ctx)), 594*0fca6ea1SDimitry Andric Mover(std::make_unique<IRMover>(*CombinedModule)) { 595*0fca6ea1SDimitry Andric CombinedModule->IsNewDbgInfoFormat = UseNewDbgInfoFormat; 596*0fca6ea1SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) 5990b57cec5SDimitry Andric : Backend(Backend), CombinedIndex(/*HaveGVs*/ false) { 6000b57cec5SDimitry Andric if (!Backend) 6010b57cec5SDimitry Andric this->Backend = 6020b57cec5SDimitry Andric createInProcessThinBackend(llvm::heavyweight_hardware_concurrency()); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric LTO::LTO(Config Conf, ThinBackend Backend, 60606c3fb27SDimitry Andric unsigned ParallelCodeGenParallelismLevel, LTOKind LTOMode) 6070b57cec5SDimitry Andric : Conf(std::move(Conf)), 6080b57cec5SDimitry Andric RegularLTO(ParallelCodeGenParallelismLevel, this->Conf), 6091db9f3b2SDimitry Andric ThinLTO(std::move(Backend)), 6101db9f3b2SDimitry Andric GlobalResolutions(std::make_optional<StringMap<GlobalResolution>>()), 6111db9f3b2SDimitry Andric LTOMode(LTOMode) {} 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // Requires a destructor for MapVector<BitcodeModule>. 6140b57cec5SDimitry Andric LTO::~LTO() = default; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // Add the symbols in the given module to the GlobalResolutions map, and resolve 6170b57cec5SDimitry Andric // their partitions. 6180b57cec5SDimitry Andric void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms, 6190b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res, 6200b57cec5SDimitry Andric unsigned Partition, bool InSummary) { 6210b57cec5SDimitry Andric auto *ResI = Res.begin(); 6220b57cec5SDimitry Andric auto *ResE = Res.end(); 6230b57cec5SDimitry Andric (void)ResE; 624349cc55cSDimitry Andric const Triple TT(RegularLTO.CombinedModule->getTargetTriple()); 6250b57cec5SDimitry Andric for (const InputFile::Symbol &Sym : Syms) { 6260b57cec5SDimitry Andric assert(ResI != ResE); 6270b57cec5SDimitry Andric SymbolResolution Res = *ResI++; 6280b57cec5SDimitry Andric 6291db9f3b2SDimitry Andric auto &GlobalRes = (*GlobalResolutions)[Sym.getName()]; 6300b57cec5SDimitry Andric GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr(); 6310b57cec5SDimitry Andric if (Res.Prevailing) { 6320b57cec5SDimitry Andric assert(!GlobalRes.Prevailing && 6330b57cec5SDimitry Andric "Multiple prevailing defs are not allowed"); 6340b57cec5SDimitry Andric GlobalRes.Prevailing = true; 6355ffd83dbSDimitry Andric GlobalRes.IRName = std::string(Sym.getIRName()); 6360b57cec5SDimitry Andric } else if (!GlobalRes.Prevailing && GlobalRes.IRName.empty()) { 6370b57cec5SDimitry Andric // Sometimes it can be two copies of symbol in a module and prevailing 6380b57cec5SDimitry Andric // symbol can have no IR name. That might happen if symbol is defined in 6390b57cec5SDimitry Andric // module level inline asm block. In case we have multiple modules with 6400b57cec5SDimitry Andric // the same symbol we want to use IR name of the prevailing symbol. 6410b57cec5SDimitry Andric // Otherwise, if we haven't seen a prevailing symbol, set the name so that 6420b57cec5SDimitry Andric // we can later use it to check if there is any prevailing copy in IR. 6435ffd83dbSDimitry Andric GlobalRes.IRName = std::string(Sym.getIRName()); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 646bdd1243dSDimitry Andric // In rare occasion, the symbol used to initialize GlobalRes has a different 647bdd1243dSDimitry Andric // IRName from the inspected Symbol. This can happen on macOS + iOS, when a 648bdd1243dSDimitry Andric // symbol is referenced through its mangled name, say @"\01_symbol" while 649bdd1243dSDimitry Andric // the IRName is @symbol (the prefix underscore comes from MachO mangling). 650bdd1243dSDimitry Andric // In that case, we have the same actual Symbol that can get two different 651bdd1243dSDimitry Andric // GUID, leading to some invalid internalization. Workaround this by marking 652bdd1243dSDimitry Andric // the GlobalRes external. 653bdd1243dSDimitry Andric 654bdd1243dSDimitry Andric // FIXME: instead of this check, it would be desirable to compute GUIDs 655bdd1243dSDimitry Andric // based on mangled name, but this requires an access to the Target Triple 656bdd1243dSDimitry Andric // and would be relatively invasive on the codebase. 657bdd1243dSDimitry Andric if (GlobalRes.IRName != Sym.getIRName()) { 658bdd1243dSDimitry Andric GlobalRes.Partition = GlobalResolution::External; 659bdd1243dSDimitry Andric GlobalRes.VisibleOutsideSummary = true; 660bdd1243dSDimitry Andric } 661bdd1243dSDimitry Andric 6620b57cec5SDimitry Andric // Set the partition to external if we know it is re-defined by the linker 6630b57cec5SDimitry Andric // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a 664fe6060f1SDimitry Andric // regular object, is referenced from llvm.compiler.used/llvm.used, or was 665fe6060f1SDimitry Andric // already recorded as being referenced from a different partition. 6660b57cec5SDimitry Andric if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || 6670b57cec5SDimitry Andric (GlobalRes.Partition != GlobalResolution::Unknown && 6680b57cec5SDimitry Andric GlobalRes.Partition != Partition)) { 6690b57cec5SDimitry Andric GlobalRes.Partition = GlobalResolution::External; 6700b57cec5SDimitry Andric } else 6710b57cec5SDimitry Andric // First recorded reference, save the current partition. 6720b57cec5SDimitry Andric GlobalRes.Partition = Partition; 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric // Flag as visible outside of summary if visible from a regular object or 6750b57cec5SDimitry Andric // from a module that does not have a summary. 6760b57cec5SDimitry Andric GlobalRes.VisibleOutsideSummary |= 6770b57cec5SDimitry Andric (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary); 678fe6060f1SDimitry Andric 679fe6060f1SDimitry Andric GlobalRes.ExportDynamic |= Res.ExportDynamic; 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric static void writeToResolutionFile(raw_ostream &OS, InputFile *Input, 6840b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res) { 6850b57cec5SDimitry Andric StringRef Path = Input->getName(); 6860b57cec5SDimitry Andric OS << Path << '\n'; 6870b57cec5SDimitry Andric auto ResI = Res.begin(); 6880b57cec5SDimitry Andric for (const InputFile::Symbol &Sym : Input->symbols()) { 6890b57cec5SDimitry Andric assert(ResI != Res.end()); 6900b57cec5SDimitry Andric SymbolResolution Res = *ResI++; 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric OS << "-r=" << Path << ',' << Sym.getName() << ','; 6930b57cec5SDimitry Andric if (Res.Prevailing) 6940b57cec5SDimitry Andric OS << 'p'; 6950b57cec5SDimitry Andric if (Res.FinalDefinitionInLinkageUnit) 6960b57cec5SDimitry Andric OS << 'l'; 6970b57cec5SDimitry Andric if (Res.VisibleToRegularObj) 6980b57cec5SDimitry Andric OS << 'x'; 6990b57cec5SDimitry Andric if (Res.LinkerRedefined) 7000b57cec5SDimitry Andric OS << 'r'; 7010b57cec5SDimitry Andric OS << '\n'; 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric OS.flush(); 7040b57cec5SDimitry Andric assert(ResI == Res.end()); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric Error LTO::add(std::unique_ptr<InputFile> Input, 7080b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res) { 7090b57cec5SDimitry Andric assert(!CalledGetMaxTasks); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric if (Conf.ResolutionFile) 7120b57cec5SDimitry Andric writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res); 7130b57cec5SDimitry Andric 714fe6060f1SDimitry Andric if (RegularLTO.CombinedModule->getTargetTriple().empty()) { 7150b57cec5SDimitry Andric RegularLTO.CombinedModule->setTargetTriple(Input->getTargetTriple()); 716fe6060f1SDimitry Andric if (Triple(Input->getTargetTriple()).isOSBinFormatELF()) 717fe6060f1SDimitry Andric Conf.VisibilityScheme = Config::ELF; 718fe6060f1SDimitry Andric } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric const SymbolResolution *ResI = Res.begin(); 7210b57cec5SDimitry Andric for (unsigned I = 0; I != Input->Mods.size(); ++I) 7220b57cec5SDimitry Andric if (Error Err = addModule(*Input, I, ResI, Res.end())) 7230b57cec5SDimitry Andric return Err; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric assert(ResI == Res.end()); 7260b57cec5SDimitry Andric return Error::success(); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric Error LTO::addModule(InputFile &Input, unsigned ModI, 7300b57cec5SDimitry Andric const SymbolResolution *&ResI, 7310b57cec5SDimitry Andric const SymbolResolution *ResE) { 7320b57cec5SDimitry Andric Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo(); 7330b57cec5SDimitry Andric if (!LTOInfo) 7340b57cec5SDimitry Andric return LTOInfo.takeError(); 7350b57cec5SDimitry Andric 73681ad6265SDimitry Andric if (EnableSplitLTOUnit) { 7370b57cec5SDimitry Andric // If only some modules were split, flag this in the index so that 7380b57cec5SDimitry Andric // we can skip or error on optimizations that need consistently split 7390b57cec5SDimitry Andric // modules (whole program devirt and lower type tests). 74081ad6265SDimitry Andric if (*EnableSplitLTOUnit != LTOInfo->EnableSplitLTOUnit) 7410b57cec5SDimitry Andric ThinLTO.CombinedIndex.setPartiallySplitLTOUnits(); 7420b57cec5SDimitry Andric } else 7430b57cec5SDimitry Andric EnableSplitLTOUnit = LTOInfo->EnableSplitLTOUnit; 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric BitcodeModule BM = Input.Mods[ModI]; 74606c3fb27SDimitry Andric 74706c3fb27SDimitry Andric if ((LTOMode == LTOK_UnifiedRegular || LTOMode == LTOK_UnifiedThin) && 74806c3fb27SDimitry Andric !LTOInfo->UnifiedLTO) 74906c3fb27SDimitry Andric return make_error<StringError>( 75006c3fb27SDimitry Andric "unified LTO compilation must use " 75106c3fb27SDimitry Andric "compatible bitcode modules (use -funified-lto)", 75206c3fb27SDimitry Andric inconvertibleErrorCode()); 75306c3fb27SDimitry Andric 75406c3fb27SDimitry Andric if (LTOInfo->UnifiedLTO && LTOMode == LTOK_Default) 75506c3fb27SDimitry Andric LTOMode = LTOK_UnifiedThin; 75606c3fb27SDimitry Andric 75706c3fb27SDimitry Andric bool IsThinLTO = LTOInfo->IsThinLTO && (LTOMode != LTOK_UnifiedRegular); 75806c3fb27SDimitry Andric 7590b57cec5SDimitry Andric auto ModSyms = Input.module_symbols(ModI); 7600b57cec5SDimitry Andric addModuleToGlobalRes(ModSyms, {ResI, ResE}, 76106c3fb27SDimitry Andric IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0, 7620b57cec5SDimitry Andric LTOInfo->HasSummary); 7630b57cec5SDimitry Andric 76406c3fb27SDimitry Andric if (IsThinLTO) 7650b57cec5SDimitry Andric return addThinLTO(BM, ModSyms, ResI, ResE); 7660b57cec5SDimitry Andric 7675ffd83dbSDimitry Andric RegularLTO.EmptyCombinedModule = false; 7680b57cec5SDimitry Andric Expected<RegularLTOState::AddedModule> ModOrErr = 7690b57cec5SDimitry Andric addRegularLTO(BM, ModSyms, ResI, ResE); 7700b57cec5SDimitry Andric if (!ModOrErr) 7710b57cec5SDimitry Andric return ModOrErr.takeError(); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (!LTOInfo->HasSummary) 7740b57cec5SDimitry Andric return linkRegularLTO(std::move(*ModOrErr), /*LivenessFromIndex=*/false); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // Regular LTO module summaries are added to a dummy module that represents 7770b57cec5SDimitry Andric // the combined regular LTO module. 7785f757f3fSDimitry Andric if (Error Err = BM.readSummary(ThinLTO.CombinedIndex, "")) 7790b57cec5SDimitry Andric return Err; 7800b57cec5SDimitry Andric RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr)); 7810b57cec5SDimitry Andric return Error::success(); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric // Checks whether the given global value is in a non-prevailing comdat 7850b57cec5SDimitry Andric // (comdat containing values the linker indicated were not prevailing, 7860b57cec5SDimitry Andric // which we then dropped to available_externally), and if so, removes 7870b57cec5SDimitry Andric // it from the comdat. This is called for all global values to ensure the 7880b57cec5SDimitry Andric // comdat is empty rather than leaving an incomplete comdat. It is needed for 7890b57cec5SDimitry Andric // regular LTO modules, in case we are in a mixed-LTO mode (both regular 7900b57cec5SDimitry Andric // and thin LTO modules) compilation. Since the regular LTO module will be 7910b57cec5SDimitry Andric // linked first in the final native link, we want to make sure the linker 7920b57cec5SDimitry Andric // doesn't select any of these incomplete comdats that would be left 7930b57cec5SDimitry Andric // in the regular LTO module without this cleanup. 7940b57cec5SDimitry Andric static void 7950b57cec5SDimitry Andric handleNonPrevailingComdat(GlobalValue &GV, 7960b57cec5SDimitry Andric std::set<const Comdat *> &NonPrevailingComdats) { 7970b57cec5SDimitry Andric Comdat *C = GV.getComdat(); 7980b57cec5SDimitry Andric if (!C) 7990b57cec5SDimitry Andric return; 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric if (!NonPrevailingComdats.count(C)) 8020b57cec5SDimitry Andric return; 8030b57cec5SDimitry Andric 804bdd1243dSDimitry Andric // Additionally need to drop all global values from the comdat to 805bdd1243dSDimitry Andric // available_externally, to satisfy the COMDAT requirement that all members 806bdd1243dSDimitry Andric // are discarded as a unit. The non-local linkage global values avoid 807bdd1243dSDimitry Andric // duplicate definition linker errors. 8080b57cec5SDimitry Andric GV.setLinkage(GlobalValue::AvailableExternallyLinkage); 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric if (auto GO = dyn_cast<GlobalObject>(&GV)) 8110b57cec5SDimitry Andric GO->setComdat(nullptr); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric // Add a regular LTO object to the link. 8150b57cec5SDimitry Andric // The resulting module needs to be linked into the combined LTO module with 8160b57cec5SDimitry Andric // linkRegularLTO. 8170b57cec5SDimitry Andric Expected<LTO::RegularLTOState::AddedModule> 8180b57cec5SDimitry Andric LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 8190b57cec5SDimitry Andric const SymbolResolution *&ResI, 8200b57cec5SDimitry Andric const SymbolResolution *ResE) { 8210b57cec5SDimitry Andric RegularLTOState::AddedModule Mod; 8220b57cec5SDimitry Andric Expected<std::unique_ptr<Module>> MOrErr = 8230b57cec5SDimitry Andric BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true, 8240b57cec5SDimitry Andric /*IsImporting*/ false); 8250b57cec5SDimitry Andric if (!MOrErr) 8260b57cec5SDimitry Andric return MOrErr.takeError(); 8270b57cec5SDimitry Andric Module &M = **MOrErr; 8280b57cec5SDimitry Andric Mod.M = std::move(*MOrErr); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric if (Error Err = M.materializeMetadata()) 8310b57cec5SDimitry Andric return std::move(Err); 83206c3fb27SDimitry Andric 83306c3fb27SDimitry Andric // If cfi.functions is present and we are in regular LTO mode, LowerTypeTests 83406c3fb27SDimitry Andric // will rename local functions in the merged module as "<function name>.1". 83506c3fb27SDimitry Andric // This causes linking errors, since other parts of the module expect the 83606c3fb27SDimitry Andric // original function name. 83706c3fb27SDimitry Andric if (LTOMode == LTOK_UnifiedRegular) 83806c3fb27SDimitry Andric if (NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions")) 83906c3fb27SDimitry Andric M.eraseNamedMetadata(CfiFunctionsMD); 84006c3fb27SDimitry Andric 8410b57cec5SDimitry Andric UpgradeDebugInfo(M); 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric ModuleSymbolTable SymTab; 8440b57cec5SDimitry Andric SymTab.addModule(&M); 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric for (GlobalVariable &GV : M.globals()) 8470b57cec5SDimitry Andric if (GV.hasAppendingLinkage()) 8480b57cec5SDimitry Andric Mod.Keep.push_back(&GV); 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric DenseSet<GlobalObject *> AliasedGlobals; 8510b57cec5SDimitry Andric for (auto &GA : M.aliases()) 852349cc55cSDimitry Andric if (GlobalObject *GO = GA.getAliaseeObject()) 8530b57cec5SDimitry Andric AliasedGlobals.insert(GO); 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric // In this function we need IR GlobalValues matching the symbols in Syms 8560b57cec5SDimitry Andric // (which is not backed by a module), so we need to enumerate them in the same 8570b57cec5SDimitry Andric // order. The symbol enumeration order of a ModuleSymbolTable intentionally 8580b57cec5SDimitry Andric // matches the order of an irsymtab, but when we read the irsymtab in 8590b57cec5SDimitry Andric // InputFile::create we omit some symbols that are irrelevant to LTO. The 8600b57cec5SDimitry Andric // Skip() function skips the same symbols from the module as InputFile does 8610b57cec5SDimitry Andric // from the symbol table. 8620b57cec5SDimitry Andric auto MsymI = SymTab.symbols().begin(), MsymE = SymTab.symbols().end(); 8630b57cec5SDimitry Andric auto Skip = [&]() { 8640b57cec5SDimitry Andric while (MsymI != MsymE) { 8650b57cec5SDimitry Andric auto Flags = SymTab.getSymbolFlags(*MsymI); 8660b57cec5SDimitry Andric if ((Flags & object::BasicSymbolRef::SF_Global) && 8670b57cec5SDimitry Andric !(Flags & object::BasicSymbolRef::SF_FormatSpecific)) 8680b57cec5SDimitry Andric return; 8690b57cec5SDimitry Andric ++MsymI; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric }; 8720b57cec5SDimitry Andric Skip(); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric std::set<const Comdat *> NonPrevailingComdats; 875fe6060f1SDimitry Andric SmallSet<StringRef, 2> NonPrevailingAsmSymbols; 8760b57cec5SDimitry Andric for (const InputFile::Symbol &Sym : Syms) { 8770b57cec5SDimitry Andric assert(ResI != ResE); 8780b57cec5SDimitry Andric SymbolResolution Res = *ResI++; 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric assert(MsymI != MsymE); 8810b57cec5SDimitry Andric ModuleSymbolTable::Symbol Msym = *MsymI++; 8820b57cec5SDimitry Andric Skip(); 8830b57cec5SDimitry Andric 88406c3fb27SDimitry Andric if (GlobalValue *GV = dyn_cast_if_present<GlobalValue *>(Msym)) { 8850b57cec5SDimitry Andric if (Res.Prevailing) { 8860b57cec5SDimitry Andric if (Sym.isUndefined()) 8870b57cec5SDimitry Andric continue; 8880b57cec5SDimitry Andric Mod.Keep.push_back(GV); 8890b57cec5SDimitry Andric // For symbols re-defined with linker -wrap and -defsym options, 8900b57cec5SDimitry Andric // set the linkage to weak to inhibit IPO. The linkage will be 8910b57cec5SDimitry Andric // restored by the linker. 8920b57cec5SDimitry Andric if (Res.LinkerRedefined) 8930b57cec5SDimitry Andric GV->setLinkage(GlobalValue::WeakAnyLinkage); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric GlobalValue::LinkageTypes OriginalLinkage = GV->getLinkage(); 8960b57cec5SDimitry Andric if (GlobalValue::isLinkOnceLinkage(OriginalLinkage)) 8970b57cec5SDimitry Andric GV->setLinkage(GlobalValue::getWeakLinkage( 8980b57cec5SDimitry Andric GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))); 8990b57cec5SDimitry Andric } else if (isa<GlobalObject>(GV) && 9000b57cec5SDimitry Andric (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() || 9010b57cec5SDimitry Andric GV->hasAvailableExternallyLinkage()) && 9020b57cec5SDimitry Andric !AliasedGlobals.count(cast<GlobalObject>(GV))) { 9030b57cec5SDimitry Andric // Any of the above three types of linkage indicates that the 9040b57cec5SDimitry Andric // chosen prevailing symbol will have the same semantics as this copy of 9050b57cec5SDimitry Andric // the symbol, so we may be able to link it with available_externally 9060b57cec5SDimitry Andric // linkage. We will decide later whether to do that when we link this 9070b57cec5SDimitry Andric // module (in linkRegularLTO), based on whether it is undefined. 9080b57cec5SDimitry Andric Mod.Keep.push_back(GV); 9090b57cec5SDimitry Andric GV->setLinkage(GlobalValue::AvailableExternallyLinkage); 9100b57cec5SDimitry Andric if (GV->hasComdat()) 9110b57cec5SDimitry Andric NonPrevailingComdats.insert(GV->getComdat()); 9120b57cec5SDimitry Andric cast<GlobalObject>(GV)->setComdat(nullptr); 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric // Set the 'local' flag based on the linker resolution for this symbol. 9160b57cec5SDimitry Andric if (Res.FinalDefinitionInLinkageUnit) { 9170b57cec5SDimitry Andric GV->setDSOLocal(true); 9180b57cec5SDimitry Andric if (GV->hasDLLImportStorageClass()) 9190b57cec5SDimitry Andric GV->setDLLStorageClass(GlobalValue::DLLStorageClassTypes:: 9200b57cec5SDimitry Andric DefaultStorageClass); 9210b57cec5SDimitry Andric } 92206c3fb27SDimitry Andric } else if (auto *AS = 92306c3fb27SDimitry Andric dyn_cast_if_present<ModuleSymbolTable::AsmSymbol *>(Msym)) { 924fe6060f1SDimitry Andric // Collect non-prevailing symbols. 925fe6060f1SDimitry Andric if (!Res.Prevailing) 926fe6060f1SDimitry Andric NonPrevailingAsmSymbols.insert(AS->first); 927fe6060f1SDimitry Andric } else { 928fe6060f1SDimitry Andric llvm_unreachable("unknown symbol type"); 9290b57cec5SDimitry Andric } 930fe6060f1SDimitry Andric 9310b57cec5SDimitry Andric // Common resolution: collect the maximum size/alignment over all commons. 9320b57cec5SDimitry Andric // We also record if we see an instance of a common as prevailing, so that 9330b57cec5SDimitry Andric // if none is prevailing we can ignore it later. 9340b57cec5SDimitry Andric if (Sym.isCommon()) { 9350b57cec5SDimitry Andric // FIXME: We should figure out what to do about commons defined by asm. 9360b57cec5SDimitry Andric // For now they aren't reported correctly by ModuleSymbolTable. 9375ffd83dbSDimitry Andric auto &CommonRes = RegularLTO.Commons[std::string(Sym.getIRName())]; 9380b57cec5SDimitry Andric CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize()); 93981ad6265SDimitry Andric if (uint32_t SymAlignValue = Sym.getCommonAlignment()) { 94006c3fb27SDimitry Andric CommonRes.Alignment = 94106c3fb27SDimitry Andric std::max(Align(SymAlignValue), CommonRes.Alignment); 94281ad6265SDimitry Andric } 9430b57cec5SDimitry Andric CommonRes.Prevailing |= Res.Prevailing; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric } 946fe6060f1SDimitry Andric 9470b57cec5SDimitry Andric if (!M.getComdatSymbolTable().empty()) 9480b57cec5SDimitry Andric for (GlobalValue &GV : M.global_values()) 9490b57cec5SDimitry Andric handleNonPrevailingComdat(GV, NonPrevailingComdats); 950fe6060f1SDimitry Andric 951fe6060f1SDimitry Andric // Prepend ".lto_discard <sym>, <sym>*" directive to each module inline asm 952fe6060f1SDimitry Andric // block. 953fe6060f1SDimitry Andric if (!M.getModuleInlineAsm().empty()) { 954fe6060f1SDimitry Andric std::string NewIA = ".lto_discard"; 955fe6060f1SDimitry Andric if (!NonPrevailingAsmSymbols.empty()) { 956fe6060f1SDimitry Andric // Don't dicard a symbol if there is a live .symver for it. 957fe6060f1SDimitry Andric ModuleSymbolTable::CollectAsmSymvers( 958fe6060f1SDimitry Andric M, [&](StringRef Name, StringRef Alias) { 959fe6060f1SDimitry Andric if (!NonPrevailingAsmSymbols.count(Alias)) 960fe6060f1SDimitry Andric NonPrevailingAsmSymbols.erase(Name); 961fe6060f1SDimitry Andric }); 962fe6060f1SDimitry Andric NewIA += " " + llvm::join(NonPrevailingAsmSymbols, ", "); 963fe6060f1SDimitry Andric } 964fe6060f1SDimitry Andric NewIA += "\n"; 965fe6060f1SDimitry Andric M.setModuleInlineAsm(NewIA + M.getModuleInlineAsm()); 966fe6060f1SDimitry Andric } 967fe6060f1SDimitry Andric 9680b57cec5SDimitry Andric assert(MsymI == MsymE); 9690b57cec5SDimitry Andric return std::move(Mod); 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod, 9730b57cec5SDimitry Andric bool LivenessFromIndex) { 9740b57cec5SDimitry Andric std::vector<GlobalValue *> Keep; 9750b57cec5SDimitry Andric for (GlobalValue *GV : Mod.Keep) { 9765ffd83dbSDimitry Andric if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) { 9775ffd83dbSDimitry Andric if (Function *F = dyn_cast<Function>(GV)) { 978349cc55cSDimitry Andric if (DiagnosticOutputFile) { 979349cc55cSDimitry Andric if (Error Err = F->materialize()) 980349cc55cSDimitry Andric return Err; 981e8d8bef9SDimitry Andric OptimizationRemarkEmitter ORE(F, nullptr); 9825ffd83dbSDimitry Andric ORE.emit(OptimizationRemark(DEBUG_TYPE, "deadfunction", F) 9835ffd83dbSDimitry Andric << ore::NV("Function", F) 9845ffd83dbSDimitry Andric << " not added to the combined module "); 9855ffd83dbSDimitry Andric } 986349cc55cSDimitry Andric } 9870b57cec5SDimitry Andric continue; 9885ffd83dbSDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric if (!GV->hasAvailableExternallyLinkage()) { 9910b57cec5SDimitry Andric Keep.push_back(GV); 9920b57cec5SDimitry Andric continue; 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric // Only link available_externally definitions if we don't already have a 9960b57cec5SDimitry Andric // definition. 9970b57cec5SDimitry Andric GlobalValue *CombinedGV = 9980b57cec5SDimitry Andric RegularLTO.CombinedModule->getNamedValue(GV->getName()); 9990b57cec5SDimitry Andric if (CombinedGV && !CombinedGV->isDeclaration()) 10000b57cec5SDimitry Andric continue; 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric Keep.push_back(GV); 10030b57cec5SDimitry Andric } 10040b57cec5SDimitry Andric 100581ad6265SDimitry Andric return RegularLTO.Mover->move(std::move(Mod.M), Keep, nullptr, 10060b57cec5SDimitry Andric /* IsPerformingImport */ false); 10070b57cec5SDimitry Andric } 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric // Add a ThinLTO module to the link. 10100b57cec5SDimitry Andric Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 10110b57cec5SDimitry Andric const SymbolResolution *&ResI, 10120b57cec5SDimitry Andric const SymbolResolution *ResE) { 1013bdd1243dSDimitry Andric const SymbolResolution *ResITmp = ResI; 1014bdd1243dSDimitry Andric for (const InputFile::Symbol &Sym : Syms) { 1015bdd1243dSDimitry Andric assert(ResITmp != ResE); 1016bdd1243dSDimitry Andric SymbolResolution Res = *ResITmp++; 1017bdd1243dSDimitry Andric 1018bdd1243dSDimitry Andric if (!Sym.getIRName().empty()) { 1019bdd1243dSDimitry Andric auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier( 1020bdd1243dSDimitry Andric Sym.getIRName(), GlobalValue::ExternalLinkage, "")); 1021bdd1243dSDimitry Andric if (Res.Prevailing) 1022bdd1243dSDimitry Andric ThinLTO.PrevailingModuleForGUID[GUID] = BM.getModuleIdentifier(); 1023bdd1243dSDimitry Andric } 1024bdd1243dSDimitry Andric } 1025bdd1243dSDimitry Andric 10260b57cec5SDimitry Andric if (Error Err = 10270b57cec5SDimitry Andric BM.readSummary(ThinLTO.CombinedIndex, BM.getModuleIdentifier(), 10285f757f3fSDimitry Andric [&](GlobalValue::GUID GUID) { 1029bdd1243dSDimitry Andric return ThinLTO.PrevailingModuleForGUID[GUID] == 1030bdd1243dSDimitry Andric BM.getModuleIdentifier(); 1031bdd1243dSDimitry Andric })) 10320b57cec5SDimitry Andric return Err; 10335f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "Module " << BM.getModuleIdentifier() << "\n"); 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric for (const InputFile::Symbol &Sym : Syms) { 10360b57cec5SDimitry Andric assert(ResI != ResE); 10370b57cec5SDimitry Andric SymbolResolution Res = *ResI++; 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric if (!Sym.getIRName().empty()) { 10400b57cec5SDimitry Andric auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier( 10410b57cec5SDimitry Andric Sym.getIRName(), GlobalValue::ExternalLinkage, "")); 10420b57cec5SDimitry Andric if (Res.Prevailing) { 1043bdd1243dSDimitry Andric assert(ThinLTO.PrevailingModuleForGUID[GUID] == 1044bdd1243dSDimitry Andric BM.getModuleIdentifier()); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric // For linker redefined symbols (via --wrap or --defsym) we want to 10470b57cec5SDimitry Andric // switch the linkage to `weak` to prevent IPOs from happening. 10480b57cec5SDimitry Andric // Find the summary in the module for this very GV and record the new 10490b57cec5SDimitry Andric // linkage so that we can switch it when we import the GV. 10500b57cec5SDimitry Andric if (Res.LinkerRedefined) 10510b57cec5SDimitry Andric if (auto S = ThinLTO.CombinedIndex.findSummaryInModule( 10520b57cec5SDimitry Andric GUID, BM.getModuleIdentifier())) 10530b57cec5SDimitry Andric S->setLinkage(GlobalValue::WeakAnyLinkage); 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric // If the linker resolved the symbol to a local definition then mark it 10570b57cec5SDimitry Andric // as local in the summary for the module we are adding. 10580b57cec5SDimitry Andric if (Res.FinalDefinitionInLinkageUnit) { 10590b57cec5SDimitry Andric if (auto S = ThinLTO.CombinedIndex.findSummaryInModule( 10600b57cec5SDimitry Andric GUID, BM.getModuleIdentifier())) { 10610b57cec5SDimitry Andric S->setDSOLocal(true); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric 10670b57cec5SDimitry Andric if (!ThinLTO.ModuleMap.insert({BM.getModuleIdentifier(), BM}).second) 10680b57cec5SDimitry Andric return make_error<StringError>( 10690b57cec5SDimitry Andric "Expected at most one ThinLTO module per bitcode file", 10700b57cec5SDimitry Andric inconvertibleErrorCode()); 10710b57cec5SDimitry Andric 10725ffd83dbSDimitry Andric if (!Conf.ThinLTOModulesToCompile.empty()) { 10735ffd83dbSDimitry Andric if (!ThinLTO.ModulesToCompile) 10745ffd83dbSDimitry Andric ThinLTO.ModulesToCompile = ModuleMapType(); 10755ffd83dbSDimitry Andric // This is a fuzzy name matching where only modules with name containing the 10765ffd83dbSDimitry Andric // specified switch values are going to be compiled. 10775ffd83dbSDimitry Andric for (const std::string &Name : Conf.ThinLTOModulesToCompile) { 10785ffd83dbSDimitry Andric if (BM.getModuleIdentifier().contains(Name)) { 10795ffd83dbSDimitry Andric ThinLTO.ModulesToCompile->insert({BM.getModuleIdentifier(), BM}); 10805ffd83dbSDimitry Andric llvm::errs() << "[ThinLTO] Selecting " << BM.getModuleIdentifier() 10815ffd83dbSDimitry Andric << " to compile\n"; 10825ffd83dbSDimitry Andric } 10835ffd83dbSDimitry Andric } 10845ffd83dbSDimitry Andric } 10855ffd83dbSDimitry Andric 10860b57cec5SDimitry Andric return Error::success(); 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric unsigned LTO::getMaxTasks() const { 10900b57cec5SDimitry Andric CalledGetMaxTasks = true; 10915ffd83dbSDimitry Andric auto ModuleCount = ThinLTO.ModulesToCompile ? ThinLTO.ModulesToCompile->size() 10925ffd83dbSDimitry Andric : ThinLTO.ModuleMap.size(); 10935ffd83dbSDimitry Andric return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric // If only some of the modules were split, we cannot correctly handle 10970b57cec5SDimitry Andric // code that contains type tests or type checked loads. 10980b57cec5SDimitry Andric Error LTO::checkPartiallySplit() { 10990b57cec5SDimitry Andric if (!ThinLTO.CombinedIndex.partiallySplitLTOUnits()) 11000b57cec5SDimitry Andric return Error::success(); 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric Function *TypeTestFunc = RegularLTO.CombinedModule->getFunction( 11030b57cec5SDimitry Andric Intrinsic::getName(Intrinsic::type_test)); 11040b57cec5SDimitry Andric Function *TypeCheckedLoadFunc = RegularLTO.CombinedModule->getFunction( 11050b57cec5SDimitry Andric Intrinsic::getName(Intrinsic::type_checked_load)); 110606c3fb27SDimitry Andric Function *TypeCheckedLoadRelativeFunc = 110706c3fb27SDimitry Andric RegularLTO.CombinedModule->getFunction( 110806c3fb27SDimitry Andric Intrinsic::getName(Intrinsic::type_checked_load_relative)); 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric // First check if there are type tests / type checked loads in the 11110b57cec5SDimitry Andric // merged regular LTO module IR. 11120b57cec5SDimitry Andric if ((TypeTestFunc && !TypeTestFunc->use_empty()) || 111306c3fb27SDimitry Andric (TypeCheckedLoadFunc && !TypeCheckedLoadFunc->use_empty()) || 111406c3fb27SDimitry Andric (TypeCheckedLoadRelativeFunc && 111506c3fb27SDimitry Andric !TypeCheckedLoadRelativeFunc->use_empty())) 11160b57cec5SDimitry Andric return make_error<StringError>( 11170b57cec5SDimitry Andric "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)", 11180b57cec5SDimitry Andric inconvertibleErrorCode()); 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric // Otherwise check if there are any recorded in the combined summary from the 11210b57cec5SDimitry Andric // ThinLTO modules. 11220b57cec5SDimitry Andric for (auto &P : ThinLTO.CombinedIndex) { 11230b57cec5SDimitry Andric for (auto &S : P.second.SummaryList) { 11240b57cec5SDimitry Andric auto *FS = dyn_cast<FunctionSummary>(S.get()); 11250b57cec5SDimitry Andric if (!FS) 11260b57cec5SDimitry Andric continue; 11270b57cec5SDimitry Andric if (!FS->type_test_assume_vcalls().empty() || 11280b57cec5SDimitry Andric !FS->type_checked_load_vcalls().empty() || 11290b57cec5SDimitry Andric !FS->type_test_assume_const_vcalls().empty() || 11300b57cec5SDimitry Andric !FS->type_checked_load_const_vcalls().empty() || 11310b57cec5SDimitry Andric !FS->type_tests().empty()) 11320b57cec5SDimitry Andric return make_error<StringError>( 11330b57cec5SDimitry Andric "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)", 11340b57cec5SDimitry Andric inconvertibleErrorCode()); 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric return Error::success(); 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 1140349cc55cSDimitry Andric Error LTO::run(AddStreamFn AddStream, FileCache Cache) { 11410b57cec5SDimitry Andric // Compute "dead" symbols, we don't want to import/export these! 11420b57cec5SDimitry Andric DenseSet<GlobalValue::GUID> GUIDPreservedSymbols; 11430b57cec5SDimitry Andric DenseMap<GlobalValue::GUID, PrevailingType> GUIDPrevailingResolutions; 11441db9f3b2SDimitry Andric for (auto &Res : *GlobalResolutions) { 11450b57cec5SDimitry Andric // Normally resolution have IR name of symbol. We can do nothing here 11460b57cec5SDimitry Andric // otherwise. See comments in GlobalResolution struct for more details. 11470b57cec5SDimitry Andric if (Res.second.IRName.empty()) 11480b57cec5SDimitry Andric continue; 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric GlobalValue::GUID GUID = GlobalValue::getGUID( 11510b57cec5SDimitry Andric GlobalValue::dropLLVMManglingEscape(Res.second.IRName)); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric if (Res.second.VisibleOutsideSummary && Res.second.Prevailing) 11548bcb0991SDimitry Andric GUIDPreservedSymbols.insert(GUID); 11550b57cec5SDimitry Andric 1156fe6060f1SDimitry Andric if (Res.second.ExportDynamic) 1157fe6060f1SDimitry Andric DynamicExportSymbols.insert(GUID); 1158fe6060f1SDimitry Andric 11590b57cec5SDimitry Andric GUIDPrevailingResolutions[GUID] = 11600b57cec5SDimitry Andric Res.second.Prevailing ? PrevailingType::Yes : PrevailingType::No; 11610b57cec5SDimitry Andric } 11620b57cec5SDimitry Andric 11630b57cec5SDimitry Andric auto isPrevailing = [&](GlobalValue::GUID G) { 11640b57cec5SDimitry Andric auto It = GUIDPrevailingResolutions.find(G); 11650b57cec5SDimitry Andric if (It == GUIDPrevailingResolutions.end()) 11660b57cec5SDimitry Andric return PrevailingType::Unknown; 11670b57cec5SDimitry Andric return It->second; 11680b57cec5SDimitry Andric }; 11690b57cec5SDimitry Andric computeDeadSymbolsWithConstProp(ThinLTO.CombinedIndex, GUIDPreservedSymbols, 11700b57cec5SDimitry Andric isPrevailing, Conf.OptLevel > 0); 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric // Setup output file to emit statistics. 11730b57cec5SDimitry Andric auto StatsFileOrErr = setupStatsFile(Conf.StatsFile); 11740b57cec5SDimitry Andric if (!StatsFileOrErr) 11750b57cec5SDimitry Andric return StatsFileOrErr.takeError(); 11760b57cec5SDimitry Andric std::unique_ptr<ToolOutputFile> StatsFile = std::move(StatsFileOrErr.get()); 11770b57cec5SDimitry Andric 117806c3fb27SDimitry Andric // TODO: Ideally this would be controlled automatically by detecting that we 117906c3fb27SDimitry Andric // are linking with an allocator that supports these interfaces, rather than 118006c3fb27SDimitry Andric // an internal option (which would still be needed for tests, however). For 118106c3fb27SDimitry Andric // example, if the library exported a symbol like __malloc_hot_cold the linker 118206c3fb27SDimitry Andric // could recognize that and set a flag in the lto::Config. 118306c3fb27SDimitry Andric if (SupportsHotColdNew) 118406c3fb27SDimitry Andric ThinLTO.CombinedIndex.setWithSupportsHotColdNew(); 118506c3fb27SDimitry Andric 11860b57cec5SDimitry Andric Error Result = runRegularLTO(AddStream); 11870b57cec5SDimitry Andric if (!Result) 11881db9f3b2SDimitry Andric // This will reset the GlobalResolutions optional once done with it to 11891db9f3b2SDimitry Andric // reduce peak memory before importing. 11900b57cec5SDimitry Andric Result = runThinLTO(AddStream, Cache, GUIDPreservedSymbols); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric if (StatsFile) 11930b57cec5SDimitry Andric PrintStatisticsJSON(StatsFile->os()); 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric return Result; 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 119806c3fb27SDimitry Andric void lto::updateMemProfAttributes(Module &Mod, 119906c3fb27SDimitry Andric const ModuleSummaryIndex &Index) { 120006c3fb27SDimitry Andric if (Index.withSupportsHotColdNew()) 120106c3fb27SDimitry Andric return; 120206c3fb27SDimitry Andric 120306c3fb27SDimitry Andric // The profile matcher applies hotness attributes directly for allocations, 120406c3fb27SDimitry Andric // and those will cause us to generate calls to the hot/cold interfaces 120506c3fb27SDimitry Andric // unconditionally. If supports-hot-cold-new was not enabled in the LTO 120606c3fb27SDimitry Andric // link then assume we don't want these calls (e.g. not linking with 120706c3fb27SDimitry Andric // the appropriate library, or otherwise trying to disable this behavior). 120806c3fb27SDimitry Andric for (auto &F : Mod) { 120906c3fb27SDimitry Andric for (auto &BB : F) { 121006c3fb27SDimitry Andric for (auto &I : BB) { 121106c3fb27SDimitry Andric auto *CI = dyn_cast<CallBase>(&I); 121206c3fb27SDimitry Andric if (!CI) 121306c3fb27SDimitry Andric continue; 121406c3fb27SDimitry Andric if (CI->hasFnAttr("memprof")) 121506c3fb27SDimitry Andric CI->removeFnAttr("memprof"); 121606c3fb27SDimitry Andric // Strip off all memprof metadata as it is no longer needed. 121706c3fb27SDimitry Andric // Importantly, this avoids the addition of new memprof attributes 121806c3fb27SDimitry Andric // after inlining propagation. 121906c3fb27SDimitry Andric // TODO: If we support additional types of MemProf metadata beyond hot 122006c3fb27SDimitry Andric // and cold, we will need to update the metadata based on the allocator 122106c3fb27SDimitry Andric // APIs supported instead of completely stripping all. 122206c3fb27SDimitry Andric CI->setMetadata(LLVMContext::MD_memprof, nullptr); 122306c3fb27SDimitry Andric CI->setMetadata(LLVMContext::MD_callsite, nullptr); 122406c3fb27SDimitry Andric } 122506c3fb27SDimitry Andric } 122606c3fb27SDimitry Andric } 122706c3fb27SDimitry Andric } 122806c3fb27SDimitry Andric 12290b57cec5SDimitry Andric Error LTO::runRegularLTO(AddStreamFn AddStream) { 12305ffd83dbSDimitry Andric // Setup optimization remarks. 12315ffd83dbSDimitry Andric auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( 12325ffd83dbSDimitry Andric RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename, 1233e8d8bef9SDimitry Andric Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness, 1234e8d8bef9SDimitry Andric Conf.RemarksHotnessThreshold); 123506c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Running regular LTO\n"); 12365ffd83dbSDimitry Andric if (!DiagFileOrErr) 12375ffd83dbSDimitry Andric return DiagFileOrErr.takeError(); 1238349cc55cSDimitry Andric DiagnosticOutputFile = std::move(*DiagFileOrErr); 12395ffd83dbSDimitry Andric 12405ffd83dbSDimitry Andric // Finalize linking of regular LTO modules containing summaries now that 12415ffd83dbSDimitry Andric // we have computed liveness information. 12425ffd83dbSDimitry Andric for (auto &M : RegularLTO.ModsWithSummaries) 12435ffd83dbSDimitry Andric if (Error Err = linkRegularLTO(std::move(M), 12445ffd83dbSDimitry Andric /*LivenessFromIndex=*/true)) 12455ffd83dbSDimitry Andric return Err; 12465ffd83dbSDimitry Andric 12475ffd83dbSDimitry Andric // Ensure we don't have inconsistently split LTO units with type tests. 12485ffd83dbSDimitry Andric // FIXME: this checks both LTO and ThinLTO. It happens to work as we take 12495ffd83dbSDimitry Andric // this path both cases but eventually this should be split into two and 12505ffd83dbSDimitry Andric // do the ThinLTO checks in `runThinLTO`. 12515ffd83dbSDimitry Andric if (Error Err = checkPartiallySplit()) 12525ffd83dbSDimitry Andric return Err; 12535ffd83dbSDimitry Andric 12540b57cec5SDimitry Andric // Make sure commons have the right size/alignment: we kept the largest from 12550b57cec5SDimitry Andric // all the prevailing when adding the inputs, and we apply it here. 12560b57cec5SDimitry Andric const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout(); 12570b57cec5SDimitry Andric for (auto &I : RegularLTO.Commons) { 12580b57cec5SDimitry Andric if (!I.second.Prevailing) 12590b57cec5SDimitry Andric // Don't do anything if no instance of this common was prevailing. 12600b57cec5SDimitry Andric continue; 12610b57cec5SDimitry Andric GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first); 12620b57cec5SDimitry Andric if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) { 12630b57cec5SDimitry Andric // Don't create a new global if the type is already correct, just make 12640b57cec5SDimitry Andric // sure the alignment is correct. 126506c3fb27SDimitry Andric OldGV->setAlignment(I.second.Alignment); 12660b57cec5SDimitry Andric continue; 12670b57cec5SDimitry Andric } 12680b57cec5SDimitry Andric ArrayType *Ty = 12690b57cec5SDimitry Andric ArrayType::get(Type::getInt8Ty(RegularLTO.Ctx), I.second.Size); 12700b57cec5SDimitry Andric auto *GV = new GlobalVariable(*RegularLTO.CombinedModule, Ty, false, 12710b57cec5SDimitry Andric GlobalValue::CommonLinkage, 12720b57cec5SDimitry Andric ConstantAggregateZero::get(Ty), ""); 127306c3fb27SDimitry Andric GV->setAlignment(I.second.Alignment); 12740b57cec5SDimitry Andric if (OldGV) { 12755f757f3fSDimitry Andric OldGV->replaceAllUsesWith(GV); 12760b57cec5SDimitry Andric GV->takeName(OldGV); 12770b57cec5SDimitry Andric OldGV->eraseFromParent(); 12780b57cec5SDimitry Andric } else { 12790b57cec5SDimitry Andric GV->setName(I.first); 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric 128306c3fb27SDimitry Andric updateMemProfAttributes(*RegularLTO.CombinedModule, ThinLTO.CombinedIndex); 128406c3fb27SDimitry Andric 12855f757f3fSDimitry Andric bool WholeProgramVisibilityEnabledInLTO = 12865f757f3fSDimitry Andric Conf.HasWholeProgramVisibility && 12875f757f3fSDimitry Andric // If validation is enabled, upgrade visibility only when all vtables 12885f757f3fSDimitry Andric // have typeinfos. 12895f757f3fSDimitry Andric (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos); 12905f757f3fSDimitry Andric 12915f757f3fSDimitry Andric // This returns true when the name is local or not defined. Locals are 12925f757f3fSDimitry Andric // expected to be handled separately. 12935f757f3fSDimitry Andric auto IsVisibleToRegularObj = [&](StringRef name) { 12941db9f3b2SDimitry Andric auto It = GlobalResolutions->find(name); 12951db9f3b2SDimitry Andric return (It == GlobalResolutions->end() || It->second.VisibleOutsideSummary); 12965f757f3fSDimitry Andric }; 12975f757f3fSDimitry Andric 12985ffd83dbSDimitry Andric // If allowed, upgrade public vcall visibility metadata to linkage unit 12995ffd83dbSDimitry Andric // visibility before whole program devirtualization in the optimizer. 13005f757f3fSDimitry Andric updateVCallVisibilityInModule( 13015f757f3fSDimitry Andric *RegularLTO.CombinedModule, WholeProgramVisibilityEnabledInLTO, 13025f757f3fSDimitry Andric DynamicExportSymbols, Conf.ValidateAllVtablesHaveTypeInfos, 13035f757f3fSDimitry Andric IsVisibleToRegularObj); 1304972a253aSDimitry Andric updatePublicTypeTestCalls(*RegularLTO.CombinedModule, 13055f757f3fSDimitry Andric WholeProgramVisibilityEnabledInLTO); 13065ffd83dbSDimitry Andric 13070b57cec5SDimitry Andric if (Conf.PreOptModuleHook && 13080b57cec5SDimitry Andric !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule)) 13090eae32dcSDimitry Andric return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric if (!Conf.CodeGenOnly) { 13121db9f3b2SDimitry Andric for (const auto &R : *GlobalResolutions) { 131306c3fb27SDimitry Andric GlobalValue *GV = 131406c3fb27SDimitry Andric RegularLTO.CombinedModule->getNamedValue(R.second.IRName); 13150b57cec5SDimitry Andric if (!R.second.isPrevailingIRSymbol()) 13160b57cec5SDimitry Andric continue; 13170b57cec5SDimitry Andric if (R.second.Partition != 0 && 13180b57cec5SDimitry Andric R.second.Partition != GlobalResolution::External) 13190b57cec5SDimitry Andric continue; 13200b57cec5SDimitry Andric 13210b57cec5SDimitry Andric // Ignore symbols defined in other partitions. 13220b57cec5SDimitry Andric // Also skip declarations, which are not allowed to have internal linkage. 13230b57cec5SDimitry Andric if (!GV || GV->hasLocalLinkage() || GV->isDeclaration()) 13240b57cec5SDimitry Andric continue; 132506c3fb27SDimitry Andric 132606c3fb27SDimitry Andric // Symbols that are marked DLLImport or DLLExport should not be 132706c3fb27SDimitry Andric // internalized, as they are either externally visible or referencing 132806c3fb27SDimitry Andric // external symbols. Symbols that have AvailableExternally or Appending 132906c3fb27SDimitry Andric // linkage might be used by future passes and should be kept as is. 133006c3fb27SDimitry Andric // These linkages are seen in Unified regular LTO, because the process 133106c3fb27SDimitry Andric // of creating split LTO units introduces symbols with that linkage into 133206c3fb27SDimitry Andric // one of the created modules. Normally, only the ThinLTO backend would 133306c3fb27SDimitry Andric // compile this module, but Unified Regular LTO processes both 133406c3fb27SDimitry Andric // modules created by the splitting process as regular LTO modules. 133506c3fb27SDimitry Andric if ((LTOMode == LTOKind::LTOK_UnifiedRegular) && 133606c3fb27SDimitry Andric ((GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) || 133706c3fb27SDimitry Andric GV->hasAvailableExternallyLinkage() || GV->hasAppendingLinkage())) 133806c3fb27SDimitry Andric continue; 133906c3fb27SDimitry Andric 13400b57cec5SDimitry Andric GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global 13410b57cec5SDimitry Andric : GlobalValue::UnnamedAddr::None); 13420b57cec5SDimitry Andric if (EnableLTOInternalization && R.second.Partition == 0) 13430b57cec5SDimitry Andric GV->setLinkage(GlobalValue::InternalLinkage); 13440b57cec5SDimitry Andric } 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andric if (Conf.PostInternalizeModuleHook && 13470b57cec5SDimitry Andric !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule)) 13480eae32dcSDimitry Andric return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); 13490b57cec5SDimitry Andric } 13505ffd83dbSDimitry Andric 13515ffd83dbSDimitry Andric if (!RegularLTO.EmptyCombinedModule || Conf.AlwaysEmitRegularLTOObj) { 1352fe6060f1SDimitry Andric if (Error Err = 1353fe6060f1SDimitry Andric backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel, 1354fe6060f1SDimitry Andric *RegularLTO.CombinedModule, ThinLTO.CombinedIndex)) 13555ffd83dbSDimitry Andric return Err; 13565ffd83dbSDimitry Andric } 13575ffd83dbSDimitry Andric 1358349cc55cSDimitry Andric return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric 1361*0fca6ea1SDimitry Andric SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) { 1362*0fca6ea1SDimitry Andric RTLIB::RuntimeLibcallsInfo Libcalls(TT); 1363*0fca6ea1SDimitry Andric SmallVector<const char *> LibcallSymbols; 1364*0fca6ea1SDimitry Andric copy_if(Libcalls.getLibcallNames(), std::back_inserter(LibcallSymbols), 1365*0fca6ea1SDimitry Andric [](const char *Name) { return Name; }); 1366*0fca6ea1SDimitry Andric return LibcallSymbols; 13678bcb0991SDimitry Andric } 13688bcb0991SDimitry Andric 13690b57cec5SDimitry Andric /// This class defines the interface to the ThinLTO backend. 13700b57cec5SDimitry Andric class lto::ThinBackendProc { 13710b57cec5SDimitry Andric protected: 1372480093f4SDimitry Andric const Config &Conf; 13730b57cec5SDimitry Andric ModuleSummaryIndex &CombinedIndex; 13745f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries; 137581ad6265SDimitry Andric lto::IndexWriteCallback OnWrite; 137681ad6265SDimitry Andric bool ShouldEmitImportsFiles; 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric public: 13795f757f3fSDimitry Andric ThinBackendProc( 13805f757f3fSDimitry Andric const Config &Conf, ModuleSummaryIndex &CombinedIndex, 13815f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 138281ad6265SDimitry Andric lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles) 13830b57cec5SDimitry Andric : Conf(Conf), CombinedIndex(CombinedIndex), 138481ad6265SDimitry Andric ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries), 138581ad6265SDimitry Andric OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles) {} 13860b57cec5SDimitry Andric 138781ad6265SDimitry Andric virtual ~ThinBackendProc() = default; 13880b57cec5SDimitry Andric virtual Error start( 13890b57cec5SDimitry Andric unsigned Task, BitcodeModule BM, 13900b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 13910b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 13920b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 13930b57cec5SDimitry Andric MapVector<StringRef, BitcodeModule> &ModuleMap) = 0; 13940b57cec5SDimitry Andric virtual Error wait() = 0; 1395e8d8bef9SDimitry Andric virtual unsigned getThreadCount() = 0; 139681ad6265SDimitry Andric 139781ad6265SDimitry Andric // Write sharded indices and (optionally) imports to disk 139881ad6265SDimitry Andric Error emitFiles(const FunctionImporter::ImportMapTy &ImportList, 139981ad6265SDimitry Andric llvm::StringRef ModulePath, 140081ad6265SDimitry Andric const std::string &NewModulePath) { 140181ad6265SDimitry Andric std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex; 1402*0fca6ea1SDimitry Andric GVSummaryPtrSet DeclarationSummaries; 1403*0fca6ea1SDimitry Andric 140481ad6265SDimitry Andric std::error_code EC; 140581ad6265SDimitry Andric gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, 1406*0fca6ea1SDimitry Andric ImportList, ModuleToSummariesForIndex, 1407*0fca6ea1SDimitry Andric DeclarationSummaries); 140881ad6265SDimitry Andric 140981ad6265SDimitry Andric raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC, 141081ad6265SDimitry Andric sys::fs::OpenFlags::OF_None); 141181ad6265SDimitry Andric if (EC) 141281ad6265SDimitry Andric return errorCodeToError(EC); 1413*0fca6ea1SDimitry Andric 1414*0fca6ea1SDimitry Andric writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex, 1415*0fca6ea1SDimitry Andric &DeclarationSummaries); 141681ad6265SDimitry Andric 141781ad6265SDimitry Andric if (ShouldEmitImportsFiles) { 141881ad6265SDimitry Andric EC = EmitImportsFiles(ModulePath, NewModulePath + ".imports", 141981ad6265SDimitry Andric ModuleToSummariesForIndex); 142081ad6265SDimitry Andric if (EC) 142181ad6265SDimitry Andric return errorCodeToError(EC); 142281ad6265SDimitry Andric } 142381ad6265SDimitry Andric return Error::success(); 142481ad6265SDimitry Andric } 14250b57cec5SDimitry Andric }; 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andric namespace { 14280b57cec5SDimitry Andric class InProcessThinBackend : public ThinBackendProc { 1429*0fca6ea1SDimitry Andric DefaultThreadPool BackendThreadPool; 14300b57cec5SDimitry Andric AddStreamFn AddStream; 1431349cc55cSDimitry Andric FileCache Cache; 14320b57cec5SDimitry Andric std::set<GlobalValue::GUID> CfiFunctionDefs; 14330b57cec5SDimitry Andric std::set<GlobalValue::GUID> CfiFunctionDecls; 14340b57cec5SDimitry Andric 1435bdd1243dSDimitry Andric std::optional<Error> Err; 14360b57cec5SDimitry Andric std::mutex ErrMu; 14370b57cec5SDimitry Andric 143881ad6265SDimitry Andric bool ShouldEmitIndexFiles; 143981ad6265SDimitry Andric 14400b57cec5SDimitry Andric public: 14410b57cec5SDimitry Andric InProcessThinBackend( 1442480093f4SDimitry Andric const Config &Conf, ModuleSummaryIndex &CombinedIndex, 14435ffd83dbSDimitry Andric ThreadPoolStrategy ThinLTOParallelism, 14445f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 144581ad6265SDimitry Andric AddStreamFn AddStream, FileCache Cache, lto::IndexWriteCallback OnWrite, 144681ad6265SDimitry Andric bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles) 144781ad6265SDimitry Andric : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries, 144881ad6265SDimitry Andric OnWrite, ShouldEmitImportsFiles), 14495ffd83dbSDimitry Andric BackendThreadPool(ThinLTOParallelism), AddStream(std::move(AddStream)), 145081ad6265SDimitry Andric Cache(std::move(Cache)), ShouldEmitIndexFiles(ShouldEmitIndexFiles) { 14510b57cec5SDimitry Andric for (auto &Name : CombinedIndex.cfiFunctionDefs()) 14520b57cec5SDimitry Andric CfiFunctionDefs.insert( 14530b57cec5SDimitry Andric GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); 14540b57cec5SDimitry Andric for (auto &Name : CombinedIndex.cfiFunctionDecls()) 14550b57cec5SDimitry Andric CfiFunctionDecls.insert( 14560b57cec5SDimitry Andric GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric Error runThinLTOBackendThread( 1460349cc55cSDimitry Andric AddStreamFn AddStream, FileCache Cache, unsigned Task, BitcodeModule BM, 1461349cc55cSDimitry Andric ModuleSummaryIndex &CombinedIndex, 14620b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 14630b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 14640b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 14650b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals, 14660b57cec5SDimitry Andric MapVector<StringRef, BitcodeModule> &ModuleMap) { 14670b57cec5SDimitry Andric auto RunThinBackend = [&](AddStreamFn AddStream) { 14680b57cec5SDimitry Andric LTOLLVMContext BackendContext(Conf); 14690b57cec5SDimitry Andric Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(BackendContext); 14700b57cec5SDimitry Andric if (!MOrErr) 14710b57cec5SDimitry Andric return MOrErr.takeError(); 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex, 1474fe6060f1SDimitry Andric ImportList, DefinedGlobals, &ModuleMap); 14750b57cec5SDimitry Andric }; 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric auto ModuleID = BM.getModuleIdentifier(); 14780b57cec5SDimitry Andric 147981ad6265SDimitry Andric if (ShouldEmitIndexFiles) { 148081ad6265SDimitry Andric if (auto E = emitFiles(ImportList, ModuleID, ModuleID.str())) 148181ad6265SDimitry Andric return E; 148281ad6265SDimitry Andric } 148381ad6265SDimitry Andric 14840b57cec5SDimitry Andric if (!Cache || !CombinedIndex.modulePaths().count(ModuleID) || 14850b57cec5SDimitry Andric all_of(CombinedIndex.getModuleHash(ModuleID), 14860b57cec5SDimitry Andric [](uint32_t V) { return V == 0; })) 14870b57cec5SDimitry Andric // Cache disabled or no entry for this module in the combined index or 14880b57cec5SDimitry Andric // no module hash. 14890b57cec5SDimitry Andric return RunThinBackend(AddStream); 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric SmallString<40> Key; 14920b57cec5SDimitry Andric // The module may be cached, this helps handling it. 14930b57cec5SDimitry Andric computeLTOCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList, 14940b57cec5SDimitry Andric ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, 14950b57cec5SDimitry Andric CfiFunctionDecls); 1496bdd1243dSDimitry Andric Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, Key, ModuleID); 1497349cc55cSDimitry Andric if (Error Err = CacheAddStreamOrErr.takeError()) 1498349cc55cSDimitry Andric return Err; 1499349cc55cSDimitry Andric AddStreamFn &CacheAddStream = *CacheAddStreamOrErr; 1500349cc55cSDimitry Andric if (CacheAddStream) 15010b57cec5SDimitry Andric return RunThinBackend(CacheAddStream); 15020b57cec5SDimitry Andric 15030b57cec5SDimitry Andric return Error::success(); 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric 15060b57cec5SDimitry Andric Error start( 15070b57cec5SDimitry Andric unsigned Task, BitcodeModule BM, 15080b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 15090b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 15100b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 15110b57cec5SDimitry Andric MapVector<StringRef, BitcodeModule> &ModuleMap) override { 15120b57cec5SDimitry Andric StringRef ModulePath = BM.getModuleIdentifier(); 15130b57cec5SDimitry Andric assert(ModuleToDefinedGVSummaries.count(ModulePath)); 15140b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals = 15150b57cec5SDimitry Andric ModuleToDefinedGVSummaries.find(ModulePath)->second; 15160b57cec5SDimitry Andric BackendThreadPool.async( 15170b57cec5SDimitry Andric [=](BitcodeModule BM, ModuleSummaryIndex &CombinedIndex, 15180b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 15190b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 15200b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> 15210b57cec5SDimitry Andric &ResolvedODR, 15220b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals, 15230b57cec5SDimitry Andric MapVector<StringRef, BitcodeModule> &ModuleMap) { 15245ffd83dbSDimitry Andric if (LLVM_ENABLE_THREADS && Conf.TimeTraceEnabled) 15255ffd83dbSDimitry Andric timeTraceProfilerInitialize(Conf.TimeTraceGranularity, 15265ffd83dbSDimitry Andric "thin backend"); 15270b57cec5SDimitry Andric Error E = runThinLTOBackendThread( 15280b57cec5SDimitry Andric AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList, 15290b57cec5SDimitry Andric ResolvedODR, DefinedGlobals, ModuleMap); 15300b57cec5SDimitry Andric if (E) { 15310b57cec5SDimitry Andric std::unique_lock<std::mutex> L(ErrMu); 15320b57cec5SDimitry Andric if (Err) 15330b57cec5SDimitry Andric Err = joinErrors(std::move(*Err), std::move(E)); 15340b57cec5SDimitry Andric else 15350b57cec5SDimitry Andric Err = std::move(E); 15360b57cec5SDimitry Andric } 15375ffd83dbSDimitry Andric if (LLVM_ENABLE_THREADS && Conf.TimeTraceEnabled) 15385ffd83dbSDimitry Andric timeTraceProfilerFinishThread(); 15390b57cec5SDimitry Andric }, 15400b57cec5SDimitry Andric BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList), 15410b57cec5SDimitry Andric std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap)); 154281ad6265SDimitry Andric 154381ad6265SDimitry Andric if (OnWrite) 154481ad6265SDimitry Andric OnWrite(std::string(ModulePath)); 15450b57cec5SDimitry Andric return Error::success(); 15460b57cec5SDimitry Andric } 15470b57cec5SDimitry Andric 15480b57cec5SDimitry Andric Error wait() override { 15490b57cec5SDimitry Andric BackendThreadPool.wait(); 15500b57cec5SDimitry Andric if (Err) 15510b57cec5SDimitry Andric return std::move(*Err); 15520b57cec5SDimitry Andric else 15530b57cec5SDimitry Andric return Error::success(); 15540b57cec5SDimitry Andric } 1555e8d8bef9SDimitry Andric 1556e8d8bef9SDimitry Andric unsigned getThreadCount() override { 1557*0fca6ea1SDimitry Andric return BackendThreadPool.getMaxConcurrency(); 1558e8d8bef9SDimitry Andric } 15590b57cec5SDimitry Andric }; 15600b57cec5SDimitry Andric } // end anonymous namespace 15610b57cec5SDimitry Andric 156281ad6265SDimitry Andric ThinBackend lto::createInProcessThinBackend(ThreadPoolStrategy Parallelism, 156381ad6265SDimitry Andric lto::IndexWriteCallback OnWrite, 156481ad6265SDimitry Andric bool ShouldEmitIndexFiles, 156581ad6265SDimitry Andric bool ShouldEmitImportsFiles) { 15665f757f3fSDimitry Andric return 15675f757f3fSDimitry Andric [=](const Config &Conf, ModuleSummaryIndex &CombinedIndex, 15685f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 1569349cc55cSDimitry Andric AddStreamFn AddStream, FileCache Cache) { 15708bcb0991SDimitry Andric return std::make_unique<InProcessThinBackend>( 15715f757f3fSDimitry Andric Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries, 15725f757f3fSDimitry Andric AddStream, Cache, OnWrite, ShouldEmitIndexFiles, 15735f757f3fSDimitry Andric ShouldEmitImportsFiles); 15740b57cec5SDimitry Andric }; 15750b57cec5SDimitry Andric } 15760b57cec5SDimitry Andric 1577*0fca6ea1SDimitry Andric StringLiteral lto::getThinLTODefaultCPU(const Triple &TheTriple) { 1578*0fca6ea1SDimitry Andric if (!TheTriple.isOSDarwin()) 1579*0fca6ea1SDimitry Andric return ""; 1580*0fca6ea1SDimitry Andric if (TheTriple.getArch() == Triple::x86_64) 1581*0fca6ea1SDimitry Andric return "core2"; 1582*0fca6ea1SDimitry Andric if (TheTriple.getArch() == Triple::x86) 1583*0fca6ea1SDimitry Andric return "yonah"; 1584*0fca6ea1SDimitry Andric if (TheTriple.isArm64e()) 1585*0fca6ea1SDimitry Andric return "apple-a12"; 1586*0fca6ea1SDimitry Andric if (TheTriple.getArch() == Triple::aarch64 || 1587*0fca6ea1SDimitry Andric TheTriple.getArch() == Triple::aarch64_32) 1588*0fca6ea1SDimitry Andric return "cyclone"; 1589*0fca6ea1SDimitry Andric return ""; 1590*0fca6ea1SDimitry Andric } 1591*0fca6ea1SDimitry Andric 15920b57cec5SDimitry Andric // Given the original \p Path to an output file, replace any path 15930b57cec5SDimitry Andric // prefix matching \p OldPrefix with \p NewPrefix. Also, create the 15940b57cec5SDimitry Andric // resulting directory if it does not yet exist. 159506c3fb27SDimitry Andric std::string lto::getThinLTOOutputFile(StringRef Path, StringRef OldPrefix, 159606c3fb27SDimitry Andric StringRef NewPrefix) { 15970b57cec5SDimitry Andric if (OldPrefix.empty() && NewPrefix.empty()) 159806c3fb27SDimitry Andric return std::string(Path); 15990b57cec5SDimitry Andric SmallString<128> NewPath(Path); 16000b57cec5SDimitry Andric llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix); 16010b57cec5SDimitry Andric StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str()); 16020b57cec5SDimitry Andric if (!ParentPath.empty()) { 16030b57cec5SDimitry Andric // Make sure the new directory exists, creating it if necessary. 16040b57cec5SDimitry Andric if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath)) 16050b57cec5SDimitry Andric llvm::errs() << "warning: could not create directory '" << ParentPath 16060b57cec5SDimitry Andric << "': " << EC.message() << '\n'; 16070b57cec5SDimitry Andric } 16087a6dacacSDimitry Andric return std::string(NewPath); 16090b57cec5SDimitry Andric } 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric namespace { 16120b57cec5SDimitry Andric class WriteIndexesThinBackend : public ThinBackendProc { 161306c3fb27SDimitry Andric std::string OldPrefix, NewPrefix, NativeObjectPrefix; 16140b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile; 16150b57cec5SDimitry Andric 16160b57cec5SDimitry Andric public: 16170b57cec5SDimitry Andric WriteIndexesThinBackend( 1618480093f4SDimitry Andric const Config &Conf, ModuleSummaryIndex &CombinedIndex, 16195f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 162006c3fb27SDimitry Andric std::string OldPrefix, std::string NewPrefix, 162106c3fb27SDimitry Andric std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, 16220b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite) 162381ad6265SDimitry Andric : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries, 162481ad6265SDimitry Andric OnWrite, ShouldEmitImportsFiles), 16250b57cec5SDimitry Andric OldPrefix(OldPrefix), NewPrefix(NewPrefix), 162606c3fb27SDimitry Andric NativeObjectPrefix(NativeObjectPrefix), 162781ad6265SDimitry Andric LinkedObjectsFile(LinkedObjectsFile) {} 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric Error start( 16300b57cec5SDimitry Andric unsigned Task, BitcodeModule BM, 16310b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 16320b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 16330b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 16340b57cec5SDimitry Andric MapVector<StringRef, BitcodeModule> &ModuleMap) override { 16350b57cec5SDimitry Andric StringRef ModulePath = BM.getModuleIdentifier(); 16360b57cec5SDimitry Andric std::string NewModulePath = 163706c3fb27SDimitry Andric getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix); 16380b57cec5SDimitry Andric 163906c3fb27SDimitry Andric if (LinkedObjectsFile) { 164006c3fb27SDimitry Andric std::string ObjectPrefix = 164106c3fb27SDimitry Andric NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix; 164206c3fb27SDimitry Andric std::string LinkedObjectsFilePath = 164306c3fb27SDimitry Andric getThinLTOOutputFile(ModulePath, OldPrefix, ObjectPrefix); 164406c3fb27SDimitry Andric *LinkedObjectsFile << LinkedObjectsFilePath << '\n'; 164506c3fb27SDimitry Andric } 16460b57cec5SDimitry Andric 164781ad6265SDimitry Andric if (auto E = emitFiles(ImportList, ModulePath, NewModulePath)) 164881ad6265SDimitry Andric return E; 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric if (OnWrite) 16515ffd83dbSDimitry Andric OnWrite(std::string(ModulePath)); 16520b57cec5SDimitry Andric return Error::success(); 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric Error wait() override { return Error::success(); } 1656e8d8bef9SDimitry Andric 1657e8d8bef9SDimitry Andric // WriteIndexesThinBackend should always return 1 to prevent module 1658e8d8bef9SDimitry Andric // re-ordering and avoid non-determinism in the final link. 1659e8d8bef9SDimitry Andric unsigned getThreadCount() override { return 1; } 16600b57cec5SDimitry Andric }; 16610b57cec5SDimitry Andric } // end anonymous namespace 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric ThinBackend lto::createWriteIndexesThinBackend( 166406c3fb27SDimitry Andric std::string OldPrefix, std::string NewPrefix, 166506c3fb27SDimitry Andric std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, 16660b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite) { 16675f757f3fSDimitry Andric return 16685f757f3fSDimitry Andric [=](const Config &Conf, ModuleSummaryIndex &CombinedIndex, 16695f757f3fSDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 1670349cc55cSDimitry Andric AddStreamFn AddStream, FileCache Cache) { 16718bcb0991SDimitry Andric return std::make_unique<WriteIndexesThinBackend>( 16725f757f3fSDimitry Andric Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix, 16735f757f3fSDimitry Andric NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles, 16745f757f3fSDimitry Andric LinkedObjectsFile, OnWrite); 16750b57cec5SDimitry Andric }; 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric 1678349cc55cSDimitry Andric Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, 16790b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) { 168006c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Running ThinLTO\n"); 1681bdd1243dSDimitry Andric ThinLTO.CombinedIndex.releaseTemporaryMemory(); 1682349cc55cSDimitry Andric timeTraceProfilerBegin("ThinLink", StringRef("")); 1683349cc55cSDimitry Andric auto TimeTraceScopeExit = llvm::make_scope_exit([]() { 1684349cc55cSDimitry Andric if (llvm::timeTraceProfilerEnabled()) 1685349cc55cSDimitry Andric llvm::timeTraceProfilerEnd(); 1686349cc55cSDimitry Andric }); 16870b57cec5SDimitry Andric if (ThinLTO.ModuleMap.empty()) 16880b57cec5SDimitry Andric return Error::success(); 16890b57cec5SDimitry Andric 16905ffd83dbSDimitry Andric if (ThinLTO.ModulesToCompile && ThinLTO.ModulesToCompile->empty()) { 16915ffd83dbSDimitry Andric llvm::errs() << "warning: [ThinLTO] No module compiled\n"; 16925ffd83dbSDimitry Andric return Error::success(); 16935ffd83dbSDimitry Andric } 16945ffd83dbSDimitry Andric 1695480093f4SDimitry Andric if (Conf.CombinedIndexHook && 1696480093f4SDimitry Andric !Conf.CombinedIndexHook(ThinLTO.CombinedIndex, GUIDPreservedSymbols)) 16970b57cec5SDimitry Andric return Error::success(); 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric // Collect for each module the list of function it defines (GUID -> 17000b57cec5SDimitry Andric // Summary). 17015f757f3fSDimitry Andric DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries( 17025f757f3fSDimitry Andric ThinLTO.ModuleMap.size()); 17030b57cec5SDimitry Andric ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule( 17040b57cec5SDimitry Andric ModuleToDefinedGVSummaries); 17050b57cec5SDimitry Andric // Create entries for any modules that didn't have any GV summaries 17060b57cec5SDimitry Andric // (either they didn't have any GVs to start with, or we suppressed 17070b57cec5SDimitry Andric // generation of the summaries because they e.g. had inline assembly 17080b57cec5SDimitry Andric // uses that couldn't be promoted/renamed on export). This is so 17090b57cec5SDimitry Andric // InProcessThinBackend::start can still launch a backend thread, which 17100b57cec5SDimitry Andric // is passed the map of summaries for the module, without any special 17110b57cec5SDimitry Andric // handling for this case. 17120b57cec5SDimitry Andric for (auto &Mod : ThinLTO.ModuleMap) 17130b57cec5SDimitry Andric if (!ModuleToDefinedGVSummaries.count(Mod.first)) 17140b57cec5SDimitry Andric ModuleToDefinedGVSummaries.try_emplace(Mod.first); 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric // Synthesize entry counts for functions in the CombinedIndex. 17170b57cec5SDimitry Andric computeSyntheticCounts(ThinLTO.CombinedIndex); 17180b57cec5SDimitry Andric 17195f757f3fSDimitry Andric DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists( 17200b57cec5SDimitry Andric ThinLTO.ModuleMap.size()); 17215f757f3fSDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists( 17220b57cec5SDimitry Andric ThinLTO.ModuleMap.size()); 17230b57cec5SDimitry Andric StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR; 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric if (DumpThinCGSCCs) 17260b57cec5SDimitry Andric ThinLTO.CombinedIndex.dumpSCCs(outs()); 17270b57cec5SDimitry Andric 17288bcb0991SDimitry Andric std::set<GlobalValue::GUID> ExportedGUIDs; 17298bcb0991SDimitry Andric 17305f757f3fSDimitry Andric bool WholeProgramVisibilityEnabledInLTO = 17315f757f3fSDimitry Andric Conf.HasWholeProgramVisibility && 17325f757f3fSDimitry Andric // If validation is enabled, upgrade visibility only when all vtables 17335f757f3fSDimitry Andric // have typeinfos. 17345f757f3fSDimitry Andric (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos); 17355f757f3fSDimitry Andric if (hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO)) 1736972a253aSDimitry Andric ThinLTO.CombinedIndex.setWithWholeProgramVisibility(); 17375f757f3fSDimitry Andric 17385f757f3fSDimitry Andric // If we're validating, get the vtable symbols that should not be 17395f757f3fSDimitry Andric // upgraded because they correspond to typeIDs outside of index-based 17405f757f3fSDimitry Andric // WPD info. 17415f757f3fSDimitry Andric DenseSet<GlobalValue::GUID> VisibleToRegularObjSymbols; 17425f757f3fSDimitry Andric if (WholeProgramVisibilityEnabledInLTO && 17435f757f3fSDimitry Andric Conf.ValidateAllVtablesHaveTypeInfos) { 17445f757f3fSDimitry Andric // This returns true when the name is local or not defined. Locals are 17455f757f3fSDimitry Andric // expected to be handled separately. 17465f757f3fSDimitry Andric auto IsVisibleToRegularObj = [&](StringRef name) { 17471db9f3b2SDimitry Andric auto It = GlobalResolutions->find(name); 17481db9f3b2SDimitry Andric return (It == GlobalResolutions->end() || 17495f757f3fSDimitry Andric It->second.VisibleOutsideSummary); 17505f757f3fSDimitry Andric }; 17515f757f3fSDimitry Andric 17525f757f3fSDimitry Andric getVisibleToRegularObjVtableGUIDs(ThinLTO.CombinedIndex, 17535f757f3fSDimitry Andric VisibleToRegularObjSymbols, 17545f757f3fSDimitry Andric IsVisibleToRegularObj); 17555f757f3fSDimitry Andric } 17565f757f3fSDimitry Andric 17575ffd83dbSDimitry Andric // If allowed, upgrade public vcall visibility to linkage unit visibility in 17585ffd83dbSDimitry Andric // the summaries before whole program devirtualization below. 17595f757f3fSDimitry Andric updateVCallVisibilityInIndex( 17605f757f3fSDimitry Andric ThinLTO.CombinedIndex, WholeProgramVisibilityEnabledInLTO, 17615f757f3fSDimitry Andric DynamicExportSymbols, VisibleToRegularObjSymbols); 17625ffd83dbSDimitry Andric 17638bcb0991SDimitry Andric // Perform index-based WPD. This will return immediately if there are 17648bcb0991SDimitry Andric // no index entries in the typeIdMetadata map (e.g. if we are instead 17658bcb0991SDimitry Andric // performing IR-based WPD in hybrid regular/thin LTO mode). 17668bcb0991SDimitry Andric std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap; 17678bcb0991SDimitry Andric runWholeProgramDevirtOnIndex(ThinLTO.CombinedIndex, ExportedGUIDs, 17688bcb0991SDimitry Andric LocalWPDTargetsMap); 17698bcb0991SDimitry Andric 177006c3fb27SDimitry Andric auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { 177106c3fb27SDimitry Andric return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath(); 177206c3fb27SDimitry Andric }; 177306c3fb27SDimitry Andric if (EnableMemProfContextDisambiguation) { 177406c3fb27SDimitry Andric MemProfContextDisambiguation ContextDisambiguation; 177506c3fb27SDimitry Andric ContextDisambiguation.run(ThinLTO.CombinedIndex, isPrevailing); 177606c3fb27SDimitry Andric } 177706c3fb27SDimitry Andric 17780b57cec5SDimitry Andric // Figure out which symbols need to be internalized. This also needs to happen 17790b57cec5SDimitry Andric // at -O0 because summary-based DCE is implemented using internalization, and 17800b57cec5SDimitry Andric // we must apply DCE consistently with the full LTO module in order to avoid 17810b57cec5SDimitry Andric // undefined references during the final link. 17821db9f3b2SDimitry Andric for (auto &Res : *GlobalResolutions) { 17830b57cec5SDimitry Andric // If the symbol does not have external references or it is not prevailing, 17840b57cec5SDimitry Andric // then not need to mark it as exported from a ThinLTO partition. 17850b57cec5SDimitry Andric if (Res.second.Partition != GlobalResolution::External || 17860b57cec5SDimitry Andric !Res.second.isPrevailingIRSymbol()) 17870b57cec5SDimitry Andric continue; 17880b57cec5SDimitry Andric auto GUID = GlobalValue::getGUID( 17890b57cec5SDimitry Andric GlobalValue::dropLLVMManglingEscape(Res.second.IRName)); 17900b57cec5SDimitry Andric // Mark exported unless index-based analysis determined it to be dead. 17910b57cec5SDimitry Andric if (ThinLTO.CombinedIndex.isGUIDLive(GUID)) 17920b57cec5SDimitry Andric ExportedGUIDs.insert(GUID); 17930b57cec5SDimitry Andric } 17940b57cec5SDimitry Andric 17951db9f3b2SDimitry Andric // Reset the GlobalResolutions to deallocate the associated memory, as there 17961db9f3b2SDimitry Andric // are no further accesses. We specifically want to do this before computing 17971db9f3b2SDimitry Andric // cross module importing, which adds to peak memory via the computed import 17981db9f3b2SDimitry Andric // and export lists. 17991db9f3b2SDimitry Andric GlobalResolutions.reset(); 18001db9f3b2SDimitry Andric 18011db9f3b2SDimitry Andric if (Conf.OptLevel > 0) 18021db9f3b2SDimitry Andric ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, 18031db9f3b2SDimitry Andric isPrevailing, ImportLists, ExportLists); 18041db9f3b2SDimitry Andric 18050b57cec5SDimitry Andric // Any functions referenced by the jump table in the regular LTO object must 18060b57cec5SDimitry Andric // be exported. 18070b57cec5SDimitry Andric for (auto &Def : ThinLTO.CombinedIndex.cfiFunctionDefs()) 18080b57cec5SDimitry Andric ExportedGUIDs.insert( 18090b57cec5SDimitry Andric GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Def))); 1810fe6060f1SDimitry Andric for (auto &Decl : ThinLTO.CombinedIndex.cfiFunctionDecls()) 1811fe6060f1SDimitry Andric ExportedGUIDs.insert( 1812fe6060f1SDimitry Andric GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Decl))); 18130b57cec5SDimitry Andric 1814480093f4SDimitry Andric auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { 18150b57cec5SDimitry Andric const auto &ExportList = ExportLists.find(ModuleIdentifier); 1816480093f4SDimitry Andric return (ExportList != ExportLists.end() && ExportList->second.count(VI)) || 1817480093f4SDimitry Andric ExportedGUIDs.count(VI.getGUID()); 18180b57cec5SDimitry Andric }; 18198bcb0991SDimitry Andric 18208bcb0991SDimitry Andric // Update local devirtualized targets that were exported by cross-module 18218bcb0991SDimitry Andric // importing or by other devirtualizations marked in the ExportedGUIDs set. 18228bcb0991SDimitry Andric updateIndexWPDForExports(ThinLTO.CombinedIndex, isExported, 18238bcb0991SDimitry Andric LocalWPDTargetsMap); 18240b57cec5SDimitry Andric 18258bcb0991SDimitry Andric thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported, 18268bcb0991SDimitry Andric isPrevailing); 18278bcb0991SDimitry Andric 18280b57cec5SDimitry Andric auto recordNewLinkage = [&](StringRef ModuleIdentifier, 18290b57cec5SDimitry Andric GlobalValue::GUID GUID, 18300b57cec5SDimitry Andric GlobalValue::LinkageTypes NewLinkage) { 18310b57cec5SDimitry Andric ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; 18320b57cec5SDimitry Andric }; 1833fe6060f1SDimitry Andric thinLTOResolvePrevailingInIndex(Conf, ThinLTO.CombinedIndex, isPrevailing, 18340b57cec5SDimitry Andric recordNewLinkage, GUIDPreservedSymbols); 18350b57cec5SDimitry Andric 1836349cc55cSDimitry Andric thinLTOPropagateFunctionAttrs(ThinLTO.CombinedIndex, isPrevailing); 1837349cc55cSDimitry Andric 18385ffd83dbSDimitry Andric generateParamAccessSummary(ThinLTO.CombinedIndex); 18395ffd83dbSDimitry Andric 1840349cc55cSDimitry Andric if (llvm::timeTraceProfilerEnabled()) 1841349cc55cSDimitry Andric llvm::timeTraceProfilerEnd(); 1842349cc55cSDimitry Andric 1843349cc55cSDimitry Andric TimeTraceScopeExit.release(); 1844349cc55cSDimitry Andric 18450b57cec5SDimitry Andric std::unique_ptr<ThinBackendProc> BackendProc = 18460b57cec5SDimitry Andric ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, 18470b57cec5SDimitry Andric AddStream, Cache); 18480b57cec5SDimitry Andric 18495ffd83dbSDimitry Andric auto &ModuleMap = 18505ffd83dbSDimitry Andric ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap; 18515ffd83dbSDimitry Andric 1852e8d8bef9SDimitry Andric auto ProcessOneModule = [&](int I) -> Error { 1853e8d8bef9SDimitry Andric auto &Mod = *(ModuleMap.begin() + I); 1854e8d8bef9SDimitry Andric // Tasks 0 through ParallelCodeGenParallelismLevel-1 are reserved for 1855e8d8bef9SDimitry Andric // combined module and parallel code generation partitions. 1856e8d8bef9SDimitry Andric return BackendProc->start(RegularLTO.ParallelCodeGenParallelismLevel + I, 1857e8d8bef9SDimitry Andric Mod.second, ImportLists[Mod.first], 1858e8d8bef9SDimitry Andric ExportLists[Mod.first], ResolvedODR[Mod.first], 1859e8d8bef9SDimitry Andric ThinLTO.ModuleMap); 1860e8d8bef9SDimitry Andric }; 18610b57cec5SDimitry Andric 1862e8d8bef9SDimitry Andric if (BackendProc->getThreadCount() == 1) { 1863e8d8bef9SDimitry Andric // Process the modules in the order they were provided on the command-line. 1864e8d8bef9SDimitry Andric // It is important for this codepath to be used for WriteIndexesThinBackend, 1865e8d8bef9SDimitry Andric // to ensure the emitted LinkedObjectsFile lists ThinLTO objects in the same 1866e8d8bef9SDimitry Andric // order as the inputs, which otherwise would affect the final link order. 1867e8d8bef9SDimitry Andric for (int I = 0, E = ModuleMap.size(); I != E; ++I) 1868e8d8bef9SDimitry Andric if (Error E = ProcessOneModule(I)) 1869e8d8bef9SDimitry Andric return E; 1870e8d8bef9SDimitry Andric } else { 1871e8d8bef9SDimitry Andric // When executing in parallel, process largest bitsize modules first to 1872e8d8bef9SDimitry Andric // improve parallelism, and avoid starving the thread pool near the end. 1873e8d8bef9SDimitry Andric // This saves about 15 sec on a 36-core machine while link `clang.exe` (out 1874e8d8bef9SDimitry Andric // of 100 sec). 1875e8d8bef9SDimitry Andric std::vector<BitcodeModule *> ModulesVec; 1876e8d8bef9SDimitry Andric ModulesVec.reserve(ModuleMap.size()); 1877e8d8bef9SDimitry Andric for (auto &Mod : ModuleMap) 1878e8d8bef9SDimitry Andric ModulesVec.push_back(&Mod.second); 1879e8d8bef9SDimitry Andric for (int I : generateModulesOrdering(ModulesVec)) 1880e8d8bef9SDimitry Andric if (Error E = ProcessOneModule(I)) 1881e8d8bef9SDimitry Andric return E; 1882e8d8bef9SDimitry Andric } 18830b57cec5SDimitry Andric return BackendProc->wait(); 18840b57cec5SDimitry Andric } 18850b57cec5SDimitry Andric 18865ffd83dbSDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> lto::setupLLVMOptimizationRemarks( 18875ffd83dbSDimitry Andric LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, 1888e8d8bef9SDimitry Andric StringRef RemarksFormat, bool RemarksWithHotness, 1889bdd1243dSDimitry Andric std::optional<uint64_t> RemarksHotnessThreshold, int Count) { 18905ffd83dbSDimitry Andric std::string Filename = std::string(RemarksFilename); 1891480093f4SDimitry Andric // For ThinLTO, file.opt.<format> becomes 1892480093f4SDimitry Andric // file.opt.<format>.thin.<num>.<format>. 18930b57cec5SDimitry Andric if (!Filename.empty() && Count != -1) 1894480093f4SDimitry Andric Filename = 1895480093f4SDimitry Andric (Twine(Filename) + ".thin." + llvm::utostr(Count) + "." + RemarksFormat) 1896480093f4SDimitry Andric .str(); 18970b57cec5SDimitry Andric 18985ffd83dbSDimitry Andric auto ResultOrErr = llvm::setupLLVMOptimizationRemarks( 1899e8d8bef9SDimitry Andric Context, Filename, RemarksPasses, RemarksFormat, RemarksWithHotness, 1900e8d8bef9SDimitry Andric RemarksHotnessThreshold); 19010b57cec5SDimitry Andric if (Error E = ResultOrErr.takeError()) 19020b57cec5SDimitry Andric return std::move(E); 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric if (*ResultOrErr) 19050b57cec5SDimitry Andric (*ResultOrErr)->keep(); 19060b57cec5SDimitry Andric 19070b57cec5SDimitry Andric return ResultOrErr; 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> 19110b57cec5SDimitry Andric lto::setupStatsFile(StringRef StatsFilename) { 19120b57cec5SDimitry Andric // Setup output file to emit statistics. 19130b57cec5SDimitry Andric if (StatsFilename.empty()) 19140b57cec5SDimitry Andric return nullptr; 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric llvm::EnableStatistics(false); 19170b57cec5SDimitry Andric std::error_code EC; 19180b57cec5SDimitry Andric auto StatsFile = 19198bcb0991SDimitry Andric std::make_unique<ToolOutputFile>(StatsFilename, EC, sys::fs::OF_None); 19200b57cec5SDimitry Andric if (EC) 19210b57cec5SDimitry Andric return errorCodeToError(EC); 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric StatsFile->keep(); 19240b57cec5SDimitry Andric return std::move(StatsFile); 19250b57cec5SDimitry Andric } 1926e8d8bef9SDimitry Andric 1927e8d8bef9SDimitry Andric // Compute the ordering we will process the inputs: the rough heuristic here 1928e8d8bef9SDimitry Andric // is to sort them per size so that the largest module get schedule as soon as 1929e8d8bef9SDimitry Andric // possible. This is purely a compile-time optimization. 1930e8d8bef9SDimitry Andric std::vector<int> lto::generateModulesOrdering(ArrayRef<BitcodeModule *> R) { 193181ad6265SDimitry Andric auto Seq = llvm::seq<int>(0, R.size()); 193281ad6265SDimitry Andric std::vector<int> ModulesOrdering(Seq.begin(), Seq.end()); 1933e8d8bef9SDimitry Andric llvm::sort(ModulesOrdering, [&](int LeftIndex, int RightIndex) { 1934e8d8bef9SDimitry Andric auto LSize = R[LeftIndex]->getBuffer().size(); 1935e8d8bef9SDimitry Andric auto RSize = R[RightIndex]->getBuffer().size(); 1936e8d8bef9SDimitry Andric return LSize > RSize; 1937e8d8bef9SDimitry Andric }); 1938e8d8bef9SDimitry Andric return ModulesOrdering; 1939e8d8bef9SDimitry Andric } 1940