17c4a1a8dSMehdi Amini //===-ThinLTOCodeGenerator.cpp - LLVM Link Time Optimizer -----------------===//
27c4a1a8dSMehdi Amini //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67c4a1a8dSMehdi Amini //
77c4a1a8dSMehdi Amini //===----------------------------------------------------------------------===//
87c4a1a8dSMehdi Amini //
97c4a1a8dSMehdi Amini // This file implements the Thin Link Time Optimization library. This library is
107c4a1a8dSMehdi Amini // intended to be used by linker to optimize code at link time.
117c4a1a8dSMehdi Amini //
127c4a1a8dSMehdi Amini //===----------------------------------------------------------------------===//
137c4a1a8dSMehdi Amini 
145c73220fSPeter Collingbourne #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
154c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
167c4a1a8dSMehdi Amini 
17f5b8a312Smodimo #include "llvm/ADT/ScopeExit.h"
18cec0cae3STeresa Johnson #include "llvm/ADT/Statistic.h"
1926ab5772STeresa Johnson #include "llvm/ADT/StringExtras.h"
20e978f6bcSFlorian Hahn #include "llvm/Analysis/AliasAnalysis.h"
21384ca190SMehdi Amini #include "llvm/Analysis/ModuleSummaryAnalysis.h"
22d9830eb7SPiotr Padlewski #include "llvm/Analysis/ProfileSummaryInfo.h"
237c4a1a8dSMehdi Amini #include "llvm/Analysis/TargetLibraryInfo.h"
24ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeReader.h"
25ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeWriter.h"
26cec0cae3STeresa Johnson #include "llvm/Bitcode/BitcodeWriterPass.h"
27432a3883SNico Weber #include "llvm/Config/llvm-config.h"
28981a7998SAdrian Prantl #include "llvm/IR/DebugInfo.h"
296bda14b3SChandler Carruth #include "llvm/IR/DiagnosticPrinter.h"
30fa5a4e1bSserge-sans-paille #include "llvm/IR/LegacyPassManager.h"
3126ab5772STeresa Johnson #include "llvm/IR/LLVMContext.h"
327531a503SFrancis Visoiu Mistrih #include "llvm/IR/LLVMRemarkStreamer.h"
337c4a1a8dSMehdi Amini #include "llvm/IR/Mangler.h"
34a43fd952SFedor Sergeev #include "llvm/IR/PassTimingInfo.h"
35981a7998SAdrian Prantl #include "llvm/IR/Verifier.h"
367c4a1a8dSMehdi Amini #include "llvm/IRReader/IRReader.h"
37df6edc52STeresa Johnson #include "llvm/LTO/LTO.h"
385a7056faSEaswaran Raman #include "llvm/LTO/SummaryBasedOptimizations.h"
397c4a1a8dSMehdi Amini #include "llvm/MC/SubtargetFeature.h"
4089b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
41059464feSMehdi Amini #include "llvm/Object/IRObjectFile.h"
42e978f6bcSFlorian Hahn #include "llvm/Passes/PassBuilder.h"
43e978f6bcSFlorian Hahn #include "llvm/Passes/StandardInstrumentations.h"
443acda917SWei Wang #include "llvm/Remarks/HotnessThresholdParser.h"
45f95f77adSMehdi Amini #include "llvm/Support/CachePruning.h"
46f95f77adSMehdi Amini #include "llvm/Support/Debug.h"
4719f176b9SMehdi Amini #include "llvm/Support/Error.h"
48f69c9178SJan Korous #include "llvm/Support/FileUtilities.h"
49f95f77adSMehdi Amini #include "llvm/Support/Path.h"
50f95f77adSMehdi Amini #include "llvm/Support/SHA1.h"
5179f2d093SWeiming Zhao #include "llvm/Support/SmallVectorMemoryBuffer.h"
527c4a1a8dSMehdi Amini #include "llvm/Support/ThreadPool.h"
53ec544c55STeresa Johnson #include "llvm/Support/Threading.h"
5419f176b9SMehdi Amini #include "llvm/Support/ToolOutputFile.h"
557c4a1a8dSMehdi Amini #include "llvm/Target/TargetMachine.h"
5620faf789Smodimo #include "llvm/Transforms/IPO/FunctionAttrs.h"
577c4a1a8dSMehdi Amini #include "llvm/Transforms/IPO/FunctionImport.h"
58059464feSMehdi Amini #include "llvm/Transforms/IPO/Internalize.h"
59eb34c3e8SEugene Leviant #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
607c4a1a8dSMehdi Amini #include "llvm/Transforms/ObjCARC.h"
617c4a1a8dSMehdi Amini #include "llvm/Transforms/Utils/FunctionImportUtils.h"
627c4a1a8dSMehdi Amini 
63819e9cdfSMehdi Amini #include <numeric>
64819e9cdfSMehdi Amini 
65089303d8SAndrew Ng #if !defined(_MSC_VER) && !defined(__MINGW32__)
66089303d8SAndrew Ng #include <unistd.h>
67089303d8SAndrew Ng #else
68089303d8SAndrew Ng #include <io.h>
69089303d8SAndrew Ng #endif
70089303d8SAndrew Ng 
717c4a1a8dSMehdi Amini using namespace llvm;
727c4a1a8dSMehdi Amini 
731aafabf7SMehdi Amini #define DEBUG_TYPE "thinlto"
741aafabf7SMehdi Amini 
7509b4a8daSMehdi Amini namespace llvm {
7609b4a8daSMehdi Amini // Flags -discard-value-names, defined in LTOCodeGenerator.cpp
7709b4a8daSMehdi Amini extern cl::opt<bool> LTODiscardValueNames;
787a21113cSFrancis Visoiu Mistrih extern cl::opt<std::string> RemarksFilename;
797a21113cSFrancis Visoiu Mistrih extern cl::opt<std::string> RemarksPasses;
807a21113cSFrancis Visoiu Mistrih extern cl::opt<bool> RemarksWithHotness;
813acda917SWei Wang extern cl::opt<Optional<uint64_t>, false, remarks::HotnessThresholdParser>
823acda917SWei Wang     RemarksHotnessThreshold;
8334667519SFrancis Visoiu Mistrih extern cl::opt<std::string> RemarksFormat;
8409b4a8daSMehdi Amini }
8509b4a8daSMehdi Amini 
867c4a1a8dSMehdi Amini namespace {
877c4a1a8dSMehdi Amini 
886f846c85SAlexandre Ganea // Default to using all available threads in the system, but using only one
896f846c85SAlexandre Ganea // thred per core, as indicated by the usage of
906f846c85SAlexandre Ganea // heavyweight_hardware_concurrency() below.
918404aeb5SAlexandre Ganea static cl::opt<int> ThreadCount("threads", cl::init(0));
927c4a1a8dSMehdi Amini 
937c4a1a8dSMehdi Amini // Simple helper to save temporary files for debug.
saveTempBitcode(const Module & TheModule,StringRef TempDir,unsigned count,StringRef Suffix)947c4a1a8dSMehdi Amini static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
957c4a1a8dSMehdi Amini                             unsigned count, StringRef Suffix) {
967c4a1a8dSMehdi Amini   if (TempDir.empty())
977c4a1a8dSMehdi Amini     return;
987c4a1a8dSMehdi Amini   // User asked to save temps, let dump the bitcode file after import.
993a13ed60SBenjamin Kramer   std::string SaveTempPath = (TempDir + llvm::Twine(count) + Suffix).str();
1007c4a1a8dSMehdi Amini   std::error_code EC;
101d9b948b6SFangrui Song   raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
1027c4a1a8dSMehdi Amini   if (EC)
1037c4a1a8dSMehdi Amini     report_fatal_error(Twine("Failed to open ") + SaveTempPath +
1047c4a1a8dSMehdi Amini                        " to save optimized bitcode\n");
1056a86e25dSRafael Espindola   WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
1067c4a1a8dSMehdi Amini }
1077c4a1a8dSMehdi Amini 
1084d2613f2STeresa Johnson static const GlobalValueSummary *
getFirstDefinitionForLinker(const GlobalValueSummaryList & GVSummaryList)1094d2613f2STeresa Johnson getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1104d2613f2STeresa Johnson   // If there is any strong definition anywhere, get it.
1114d2613f2STeresa Johnson   auto StrongDefForLinker = llvm::find_if(
1124d2613f2STeresa Johnson       GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1134d2613f2STeresa Johnson         auto Linkage = Summary->linkage();
1144d2613f2STeresa Johnson         return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1154d2613f2STeresa Johnson                !GlobalValue::isWeakForLinker(Linkage);
1164d2613f2STeresa Johnson       });
1174d2613f2STeresa Johnson   if (StrongDefForLinker != GVSummaryList.end())
1184d2613f2STeresa Johnson     return StrongDefForLinker->get();
1195a2e5d32SMehdi Amini   // Get the first *linker visible* definition for this global in the summary
1205a2e5d32SMehdi Amini   // list.
1215a2e5d32SMehdi Amini   auto FirstDefForLinker = llvm::find_if(
12228e457bcSTeresa Johnson       GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
12328e457bcSTeresa Johnson         auto Linkage = Summary->linkage();
1245a2e5d32SMehdi Amini         return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1255a2e5d32SMehdi Amini       });
1264d2613f2STeresa Johnson   // Extern templates can be emitted as available_externally.
1274d2613f2STeresa Johnson   if (FirstDefForLinker == GVSummaryList.end())
1284d2613f2STeresa Johnson     return nullptr;
1294d2613f2STeresa Johnson   return FirstDefForLinker->get();
130fa6e414eSHans Wennborg }
1315a2e5d32SMehdi Amini 
1324d2613f2STeresa Johnson // Populate map of GUID to the prevailing copy for any multiply defined
1334d2613f2STeresa Johnson // symbols. Currently assume first copy is prevailing, or any strong
1344d2613f2STeresa Johnson // definition. Can be refined with Linker information in the future.
computePrevailingCopies(const ModuleSummaryIndex & Index,DenseMap<GlobalValue::GUID,const GlobalValueSummary * > & PrevailingCopy)1354d2613f2STeresa Johnson static void computePrevailingCopies(
1364d2613f2STeresa Johnson     const ModuleSummaryIndex &Index,
1374d2613f2STeresa Johnson     DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy) {
13828e457bcSTeresa Johnson   auto HasMultipleCopies = [&](const GlobalValueSummaryList &GVSummaryList) {
13928e457bcSTeresa Johnson     return GVSummaryList.size() > 1;
14028e457bcSTeresa Johnson   };
1415a2e5d32SMehdi Amini 
1424d2613f2STeresa Johnson   for (auto &I : Index) {
1439667b91bSPeter Collingbourne     if (HasMultipleCopies(I.second.SummaryList))
1449667b91bSPeter Collingbourne       PrevailingCopy[I.first] =
1459667b91bSPeter Collingbourne           getFirstDefinitionForLinker(I.second.SummaryList);
146a71a5a62SMehdi Amini   }
1475a2e5d32SMehdi Amini }
1485a2e5d32SMehdi Amini 
14905a358cdSSteven Wu static StringMap<lto::InputFile *>
generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> & Modules)15005a358cdSSteven Wu generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {
15105a358cdSSteven Wu   StringMap<lto::InputFile *> ModuleMap;
15205a358cdSSteven Wu   for (auto &M : Modules) {
15305a358cdSSteven Wu     assert(ModuleMap.find(M->getName()) == ModuleMap.end() &&
1547c4a1a8dSMehdi Amini            "Expect unique Buffer Identifier");
15505a358cdSSteven Wu     ModuleMap[M->getName()] = M.get();
1567c4a1a8dSMehdi Amini   }
1577c4a1a8dSMehdi Amini   return ModuleMap;
1587c4a1a8dSMehdi Amini }
1597c4a1a8dSMehdi Amini 
promoteModule(Module & TheModule,const ModuleSummaryIndex & Index,bool ClearDSOLocalOnDeclarations)160d2ef8c1fSFangrui Song static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,
161d2ef8c1fSFangrui Song                           bool ClearDSOLocalOnDeclarations) {
162d2ef8c1fSFangrui Song   if (renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations))
1637c4a1a8dSMehdi Amini     report_fatal_error("renameModuleForThinLTO failed");
1647c4a1a8dSMehdi Amini }
1657c4a1a8dSMehdi Amini 
166981a7998SAdrian Prantl namespace {
167981a7998SAdrian Prantl class ThinLTODiagnosticInfo : public DiagnosticInfo {
168981a7998SAdrian Prantl   const Twine &Msg;
169981a7998SAdrian Prantl public:
ThinLTODiagnosticInfo(const Twine & DiagMsg,DiagnosticSeverity Severity=DS_Error)170981a7998SAdrian Prantl   ThinLTODiagnosticInfo(const Twine &DiagMsg,
171981a7998SAdrian Prantl                         DiagnosticSeverity Severity = DS_Error)
172981a7998SAdrian Prantl       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
print(DiagnosticPrinter & DP) const173981a7998SAdrian Prantl   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
174981a7998SAdrian Prantl };
175981a7998SAdrian Prantl }
176981a7998SAdrian Prantl 
177981a7998SAdrian Prantl /// Verify the module and strip broken debug info.
verifyLoadedModule(Module & TheModule)178981a7998SAdrian Prantl static void verifyLoadedModule(Module &TheModule) {
179981a7998SAdrian Prantl   bool BrokenDebugInfo = false;
180a8b2ddbdSAdrian Prantl   if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))
181981a7998SAdrian Prantl     report_fatal_error("Broken module found, compilation aborted!");
182981a7998SAdrian Prantl   if (BrokenDebugInfo) {
183981a7998SAdrian Prantl     TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
184981a7998SAdrian Prantl         "Invalid debug info found, debug info will be stripped", DS_Warning));
185981a7998SAdrian Prantl     StripDebugInfo(TheModule);
186981a7998SAdrian Prantl   }
187981a7998SAdrian Prantl }
188981a7998SAdrian Prantl 
loadModuleFromInput(lto::InputFile * Input,LLVMContext & Context,bool Lazy,bool IsImporting)18905a358cdSSteven Wu static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,
19005a358cdSSteven Wu                                                    LLVMContext &Context,
19105a358cdSSteven Wu                                                    bool Lazy,
19205a358cdSSteven Wu                                                    bool IsImporting) {
19305a358cdSSteven Wu   auto &Mod = Input->getSingleBitcodeModule();
194dac43b49SPeter Collingbourne   SMDiagnostic Err;
195dac43b49SPeter Collingbourne   Expected<std::unique_ptr<Module>> ModuleOrErr =
19605a358cdSSteven Wu       Lazy ? Mod.getLazyModule(Context,
197a61f5e37STeresa Johnson                                /* ShouldLazyLoadMetadata */ true, IsImporting)
19805a358cdSSteven Wu            : Mod.parseModule(Context);
199dac43b49SPeter Collingbourne   if (!ModuleOrErr) {
200dac43b49SPeter Collingbourne     handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
20105a358cdSSteven Wu       SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
202dac43b49SPeter Collingbourne                                       SourceMgr::DK_Error, EIB.message());
203dac43b49SPeter Collingbourne       Err.print("ThinLTO", errs());
204dac43b49SPeter Collingbourne     });
205dac43b49SPeter Collingbourne     report_fatal_error("Can't load module, abort.");
206dac43b49SPeter Collingbourne   }
207981a7998SAdrian Prantl   if (!Lazy)
208981a7998SAdrian Prantl     verifyLoadedModule(*ModuleOrErr.get());
20905a358cdSSteven Wu   return std::move(*ModuleOrErr);
210dac43b49SPeter Collingbourne }
211dac43b49SPeter Collingbourne 
21201e32130SMehdi Amini static void
crossImportIntoModule(Module & TheModule,const ModuleSummaryIndex & Index,StringMap<lto::InputFile * > & ModuleMap,const FunctionImporter::ImportMapTy & ImportList,bool ClearDSOLocalOnDeclarations)21301e32130SMehdi Amini crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
21405a358cdSSteven Wu                       StringMap<lto::InputFile *> &ModuleMap,
215d2ef8c1fSFangrui Song                       const FunctionImporter::ImportMapTy &ImportList,
216d2ef8c1fSFangrui Song                       bool ClearDSOLocalOnDeclarations) {
217dac43b49SPeter Collingbourne   auto Loader = [&](StringRef Identifier) {
21805a358cdSSteven Wu     auto &Input = ModuleMap[Identifier];
21905a358cdSSteven Wu     return loadModuleFromInput(Input, TheModule.getContext(),
220a61f5e37STeresa Johnson                                /*Lazy=*/true, /*IsImporting*/ true);
221dac43b49SPeter Collingbourne   };
222dac43b49SPeter Collingbourne 
223d2ef8c1fSFangrui Song   FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);
22466043797SAdrian Prantl   Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);
22583a807ebSMehdi Amini   if (!Result) {
22683a807ebSMehdi Amini     handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {
22783a807ebSMehdi Amini       SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),
22883a807ebSMehdi Amini                                       SourceMgr::DK_Error, EIB.message());
22983a807ebSMehdi Amini       Err.print("ThinLTO", errs());
23083a807ebSMehdi Amini     });
2317f00d0a1SPeter Collingbourne     report_fatal_error("importFunctions failed");
2327c4a1a8dSMehdi Amini   }
233981a7998SAdrian Prantl   // Verify again after cross-importing.
234981a7998SAdrian Prantl   verifyLoadedModule(TheModule);
23583a807ebSMehdi Amini }
2367c4a1a8dSMehdi Amini 
optimizeModule(Module & TheModule,TargetMachine & TM,unsigned OptLevel,bool Freestanding,bool DebugPassManager,ModuleSummaryIndex * Index)237cc7fbf71SMehdi Amini static void optimizeModule(Module &TheModule, TargetMachine &TM,
238eb34c3e8SEugene Leviant                            unsigned OptLevel, bool Freestanding,
239ceadf6eeSNikita Popov                            bool DebugPassManager, ModuleSummaryIndex *Index) {
240e978f6bcSFlorian Hahn   Optional<PGOOptions> PGOOpt;
241e978f6bcSFlorian Hahn   LoopAnalysisManager LAM;
242e978f6bcSFlorian Hahn   FunctionAnalysisManager FAM;
243e978f6bcSFlorian Hahn   CGSCCAnalysisManager CGAM;
244e978f6bcSFlorian Hahn   ModuleAnalysisManager MAM;
245e978f6bcSFlorian Hahn 
246e978f6bcSFlorian Hahn   PassInstrumentationCallbacks PIC;
247e978f6bcSFlorian Hahn   StandardInstrumentations SI(DebugPassManager);
248e978f6bcSFlorian Hahn   SI.registerCallbacks(PIC, &FAM);
249e978f6bcSFlorian Hahn   PipelineTuningOptions PTO;
250e978f6bcSFlorian Hahn   PTO.LoopVectorization = true;
251e978f6bcSFlorian Hahn   PTO.SLPVectorization = true;
252e978f6bcSFlorian Hahn   PassBuilder PB(&TM, PTO, PGOOpt, &PIC);
253e978f6bcSFlorian Hahn 
254e978f6bcSFlorian Hahn   std::unique_ptr<TargetLibraryInfoImpl> TLII(
255e978f6bcSFlorian Hahn       new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())));
256e978f6bcSFlorian Hahn   if (Freestanding)
257e978f6bcSFlorian Hahn     TLII->disableAllFunctions();
258e978f6bcSFlorian Hahn   FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
259e978f6bcSFlorian Hahn 
260e978f6bcSFlorian Hahn   // Register all the basic analyses with the managers.
261e978f6bcSFlorian Hahn   PB.registerModuleAnalyses(MAM);
262e978f6bcSFlorian Hahn   PB.registerCGSCCAnalyses(CGAM);
263e978f6bcSFlorian Hahn   PB.registerFunctionAnalyses(FAM);
264e978f6bcSFlorian Hahn   PB.registerLoopAnalyses(LAM);
265e978f6bcSFlorian Hahn   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
266e978f6bcSFlorian Hahn 
267e978f6bcSFlorian Hahn   ModulePassManager MPM;
268e978f6bcSFlorian Hahn 
2697a797b29STarindu Jayatilaka   OptimizationLevel OL;
270e978f6bcSFlorian Hahn 
271e978f6bcSFlorian Hahn   switch (OptLevel) {
272e978f6bcSFlorian Hahn   default:
273e978f6bcSFlorian Hahn     llvm_unreachable("Invalid optimization level");
274e978f6bcSFlorian Hahn   case 0:
2757a797b29STarindu Jayatilaka     OL = OptimizationLevel::O0;
276e978f6bcSFlorian Hahn     break;
277e978f6bcSFlorian Hahn   case 1:
2787a797b29STarindu Jayatilaka     OL = OptimizationLevel::O1;
279e978f6bcSFlorian Hahn     break;
280e978f6bcSFlorian Hahn   case 2:
2817a797b29STarindu Jayatilaka     OL = OptimizationLevel::O2;
282e978f6bcSFlorian Hahn     break;
283e978f6bcSFlorian Hahn   case 3:
2847a797b29STarindu Jayatilaka     OL = OptimizationLevel::O3;
285e978f6bcSFlorian Hahn     break;
286e978f6bcSFlorian Hahn   }
287e978f6bcSFlorian Hahn 
288e978f6bcSFlorian Hahn   MPM.addPass(PB.buildThinLTODefaultPipeline(OL, Index));
289e978f6bcSFlorian Hahn 
290e978f6bcSFlorian Hahn   MPM.run(TheModule, MAM);
291e978f6bcSFlorian Hahn }
292e978f6bcSFlorian Hahn 
29305a358cdSSteven Wu static void
addUsedSymbolToPreservedGUID(const lto::InputFile & File,DenseSet<GlobalValue::GUID> & PreservedGUID)29405a358cdSSteven Wu addUsedSymbolToPreservedGUID(const lto::InputFile &File,
29505a358cdSSteven Wu                              DenseSet<GlobalValue::GUID> &PreservedGUID) {
29605a358cdSSteven Wu   for (const auto &Sym : File.symbols()) {
29705a358cdSSteven Wu     if (Sym.isUsed())
29805a358cdSSteven Wu       PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));
29905a358cdSSteven Wu   }
30005a358cdSSteven Wu }
30105a358cdSSteven Wu 
302059464feSMehdi Amini // Convert the PreservedSymbols map from "Name" based to "GUID" based.
computeGUIDPreservedSymbols(const lto::InputFile & File,const StringSet<> & PreservedSymbols,const Triple & TheTriple,DenseSet<GlobalValue::GUID> & GUIDs)30334b289b6SSteven Wu static void computeGUIDPreservedSymbols(const lto::InputFile &File,
30434b289b6SSteven Wu                                         const StringSet<> &PreservedSymbols,
30534b289b6SSteven Wu                                         const Triple &TheTriple,
30634b289b6SSteven Wu                                         DenseSet<GlobalValue::GUID> &GUIDs) {
30734b289b6SSteven Wu   // Iterate the symbols in the input file and if the input has preserved symbol
30834b289b6SSteven Wu   // compute the GUID for the symbol.
30934b289b6SSteven Wu   for (const auto &Sym : File.symbols()) {
31097866b8dSSteven Wu     if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())
31134b289b6SSteven Wu       GUIDs.insert(GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
31234b289b6SSteven Wu           Sym.getIRName(), GlobalValue::ExternalLinkage, "")));
31334b289b6SSteven Wu   }
31434b289b6SSteven Wu }
31534b289b6SSteven Wu 
316059464feSMehdi Amini static DenseSet<GlobalValue::GUID>
computeGUIDPreservedSymbols(const lto::InputFile & File,const StringSet<> & PreservedSymbols,const Triple & TheTriple)31734b289b6SSteven Wu computeGUIDPreservedSymbols(const lto::InputFile &File,
31834b289b6SSteven Wu                             const StringSet<> &PreservedSymbols,
319059464feSMehdi Amini                             const Triple &TheTriple) {
3201380edf4SMehdi Amini   DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());
32134b289b6SSteven Wu   computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,
32234b289b6SSteven Wu                               GUIDPreservedSymbols);
3231380edf4SMehdi Amini   return GUIDPreservedSymbols;
324059464feSMehdi Amini }
325059464feSMehdi Amini 
codegenModule(Module & TheModule,TargetMachine & TM)3267c4a1a8dSMehdi Amini std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
3277c4a1a8dSMehdi Amini                                             TargetMachine &TM) {
3287c4a1a8dSMehdi Amini   SmallVector<char, 128> OutputBuffer;
3297c4a1a8dSMehdi Amini 
3307c4a1a8dSMehdi Amini   // CodeGen
3317c4a1a8dSMehdi Amini   {
3327c4a1a8dSMehdi Amini     raw_svector_ostream OS(OutputBuffer);
3337c4a1a8dSMehdi Amini     legacy::PassManager PM;
334215d59e7SMehdi Amini 
335215d59e7SMehdi Amini     // If the bitcode files contain ARC code and were compiled with optimization,
336215d59e7SMehdi Amini     // the ObjCARCContractPass must be run, so do it unconditionally here.
337215d59e7SMehdi Amini     PM.add(createObjCARCContractPass());
338215d59e7SMehdi Amini 
339215d59e7SMehdi Amini     // Setup the codegen now.
3401dfede31SReid Kleckner     if (TM.addPassesToEmitFile(PM, OS, nullptr, CGFT_ObjectFile,
3417c4a1a8dSMehdi Amini                                /* DisableVerify */ true))
3427c4a1a8dSMehdi Amini       report_fatal_error("Failed to setup codegen");
3437c4a1a8dSMehdi Amini 
3447c4a1a8dSMehdi Amini     // Run codegen now. resulting binary is in OutputBuffer.
3457c4a1a8dSMehdi Amini     PM.run(TheModule);
3467c4a1a8dSMehdi Amini   }
347d0262c23SJan Svoboda   return std::make_unique<SmallVectorMemoryBuffer>(
348d0262c23SJan Svoboda       std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
3497c4a1a8dSMehdi Amini }
3507c4a1a8dSMehdi Amini 
351f95f77adSMehdi Amini /// Manage caching for a single Module.
352f95f77adSMehdi Amini class ModuleCacheEntry {
353f95f77adSMehdi Amini   SmallString<128> EntryPath;
354f95f77adSMehdi Amini 
355f95f77adSMehdi Amini public:
356f95f77adSMehdi Amini   // Create a cache entry. This compute a unique hash for the Module considering
357f95f77adSMehdi Amini   // the current list of export/import, and offer an interface to query to
358f95f77adSMehdi Amini   // access the content in the cache.
ModuleCacheEntry(StringRef CachePath,const ModuleSummaryIndex & Index,StringRef ModuleID,const FunctionImporter::ImportMapTy & ImportList,const FunctionImporter::ExportSetTy & ExportList,const std::map<GlobalValue::GUID,GlobalValue::LinkageTypes> & ResolvedODR,const GVSummaryMapTy & DefinedGVSummaries,unsigned OptLevel,bool Freestanding,const TargetMachineBuilder & TMBuilder)359f95f77adSMehdi Amini   ModuleCacheEntry(
360f95f77adSMehdi Amini       StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,
361f95f77adSMehdi Amini       const FunctionImporter::ImportMapTy &ImportList,
362f95f77adSMehdi Amini       const FunctionImporter::ExportSetTy &ExportList,
363f95f77adSMehdi Amini       const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
3645f312ad4STeresa Johnson       const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,
365b5a46c1fSMehdi Amini       bool Freestanding, const TargetMachineBuilder &TMBuilder) {
366f95f77adSMehdi Amini     if (CachePath.empty())
367f95f77adSMehdi Amini       return;
368f95f77adSMehdi Amini 
36900fa1409SMehdi Amini     if (!Index.modulePaths().count(ModuleID))
37000fa1409SMehdi Amini       // The module does not have an entry, it can't have a hash at all
37100fa1409SMehdi Amini       return;
37200fa1409SMehdi Amini 
3735f312ad4STeresa Johnson     if (all_of(Index.getModuleHash(ModuleID),
3745f312ad4STeresa Johnson                [](uint32_t V) { return V == 0; }))
375f82bda0aSMehdi Amini       // No hash entry, no caching!
376f82bda0aSMehdi Amini       return;
377f82bda0aSMehdi Amini 
3785f312ad4STeresa Johnson     llvm::lto::Config Conf;
3795f312ad4STeresa Johnson     Conf.OptLevel = OptLevel;
3805f312ad4STeresa Johnson     Conf.Options = TMBuilder.Options;
3815f312ad4STeresa Johnson     Conf.CPU = TMBuilder.MCpu;
3825f312ad4STeresa Johnson     Conf.MAttrs.push_back(TMBuilder.MAttr);
3835f312ad4STeresa Johnson     Conf.RelocModel = TMBuilder.RelocModel;
3845f312ad4STeresa Johnson     Conf.CGOptLevel = TMBuilder.CGOptLevel;
3855f312ad4STeresa Johnson     Conf.Freestanding = Freestanding;
3865f312ad4STeresa Johnson     SmallString<40> Key;
3875f312ad4STeresa Johnson     computeLTOCacheKey(Key, Conf, Index, ModuleID, ImportList, ExportList,
3885f312ad4STeresa Johnson                        ResolvedODR, DefinedGVSummaries);
389bf46e741SEugene Leviant 
39025a17ba4SPeter Collingbourne     // This choice of file name allows the cache to be pruned (see pruneCache()
39125a17ba4SPeter Collingbourne     // in include/llvm/Support/CachePruning.h).
3925f312ad4STeresa Johnson     sys::path::append(EntryPath, CachePath, "llvmcache-" + Key);
393f95f77adSMehdi Amini   }
394f95f77adSMehdi Amini 
395059464feSMehdi Amini   // Access the path to this entry in the cache.
getEntryPath()396059464feSMehdi Amini   StringRef getEntryPath() { return EntryPath; }
397059464feSMehdi Amini 
398f95f77adSMehdi Amini   // Try loading the buffer for this cache entry.
tryLoadingBuffer()399f95f77adSMehdi Amini   ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {
400f95f77adSMehdi Amini     if (EntryPath.empty())
401f95f77adSMehdi Amini       return std::error_code();
402089303d8SAndrew Ng     SmallString<64> ResultPath;
403f002fcb2SReid Kleckner     Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForRead(
404f002fcb2SReid Kleckner         Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);
405f002fcb2SReid Kleckner     if (!FDOrErr)
406f002fcb2SReid Kleckner       return errorToErrorCode(FDOrErr.takeError());
407cc418a3aSReid Kleckner     ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getOpenFile(
408f002fcb2SReid Kleckner         *FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
409f002fcb2SReid Kleckner     sys::fs::closeFile(*FDOrErr);
410089303d8SAndrew Ng     return MBOrErr;
411f95f77adSMehdi Amini   }
412f95f77adSMehdi Amini 
413f95f77adSMehdi Amini   // Cache the Produced object file
write(const MemoryBuffer & OutputBuffer)4148e13bc45SMehdi Amini   void write(const MemoryBuffer &OutputBuffer) {
415f95f77adSMehdi Amini     if (EntryPath.empty())
4168e13bc45SMehdi Amini       return;
417f95f77adSMehdi Amini 
418f95f77adSMehdi Amini     // Write to a temporary to avoid race condition
419f95f77adSMehdi Amini     SmallString<128> TempFilename;
4200b01dfbbSEkaterina Romanova     SmallString<128> CachePath(EntryPath);
4210b01dfbbSEkaterina Romanova     llvm::sys::path::remove_filename(CachePath);
4220b01dfbbSEkaterina Romanova     sys::path::append(TempFilename, CachePath, "Thin-%%%%%%.tmp.o");
423f69c9178SJan Korous 
424f69c9178SJan Korous     if (auto Err = handleErrors(
425f69c9178SJan Korous             llvm::writeFileAtomically(TempFilename, EntryPath,
426f69c9178SJan Korous                                       OutputBuffer.getBuffer()),
427f69c9178SJan Korous             [](const llvm::AtomicFileWriteError &E) {
428f69c9178SJan Korous               std::string ErrorMsgBuffer;
429f69c9178SJan Korous               llvm::raw_string_ostream S(ErrorMsgBuffer);
430f69c9178SJan Korous               E.log(S);
431f69c9178SJan Korous 
432f69c9178SJan Korous               if (E.Error ==
433f69c9178SJan Korous                   llvm::atomic_write_error::failed_to_create_uniq_file) {
434f69c9178SJan Korous                 errs() << "Error: " << ErrorMsgBuffer << "\n";
435f95f77adSMehdi Amini                 report_fatal_error("ThinLTO: Can't get a temporary file");
436f95f77adSMehdi Amini               }
437f69c9178SJan Korous             })) {
438f69c9178SJan Korous       // FIXME
439f69c9178SJan Korous       consumeError(std::move(Err));
440f95f77adSMehdi Amini     }
441f95f77adSMehdi Amini   }
442f95f77adSMehdi Amini };
443f95f77adSMehdi Amini 
4444d2613f2STeresa Johnson static std::unique_ptr<MemoryBuffer>
ProcessThinLTOModule(Module & TheModule,ModuleSummaryIndex & Index,StringMap<lto::InputFile * > & ModuleMap,TargetMachine & TM,const FunctionImporter::ImportMapTy & ImportList,const FunctionImporter::ExportSetTy & ExportList,const DenseSet<GlobalValue::GUID> & GUIDPreservedSymbols,const GVSummaryMapTy & DefinedGlobals,const ThinLTOCodeGenerator::CachingOptions & CacheOptions,bool DisableCodeGen,StringRef SaveTempsDir,bool Freestanding,unsigned OptLevel,unsigned count,bool DebugPassManager)4454d2613f2STeresa Johnson ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
44605a358cdSSteven Wu                      StringMap<lto::InputFile *> &ModuleMap, TargetMachine &TM,
44701e32130SMehdi Amini                      const FunctionImporter::ImportMapTy &ImportList,
448059464feSMehdi Amini                      const FunctionImporter::ExportSetTy &ExportList,
449059464feSMehdi Amini                      const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
4504d2613f2STeresa Johnson                      const GVSummaryMapTy &DefinedGlobals,
451c321e534SBenjamin Kramer                      const ThinLTOCodeGenerator::CachingOptions &CacheOptions,
4524d2613f2STeresa Johnson                      bool DisableCodeGen, StringRef SaveTempsDir,
453e978f6bcSFlorian Hahn                      bool Freestanding, unsigned OptLevel, unsigned count,
454ceadf6eeSNikita Popov                      bool DebugPassManager) {
455*2eade1dbSArthur Eubanks   // See comment at call to updateVCallVisibilityInIndex() for why
456*2eade1dbSArthur Eubanks   // WholeProgramVisibilityEnabledInLTO is false.
457*2eade1dbSArthur Eubanks   updatePublicTypeTestCalls(TheModule,
458*2eade1dbSArthur Eubanks                             /* WholeProgramVisibilityEnabledInLTO */ false);
459059464feSMehdi Amini 
4607c4a1a8dSMehdi Amini   // "Benchmark"-like optimization: single-source case
4617c4a1a8dSMehdi Amini   bool SingleModule = (ModuleMap.size() == 1);
4627c4a1a8dSMehdi Amini 
463d2ef8c1fSFangrui Song   // When linking an ELF shared object, dso_local should be dropped. We
464d2ef8c1fSFangrui Song   // conservatively do this for -fpic.
465d2ef8c1fSFangrui Song   bool ClearDSOLocalOnDeclarations =
466d2ef8c1fSFangrui Song       TM.getTargetTriple().isOSBinFormatELF() &&
467d2ef8c1fSFangrui Song       TM.getRelocationModel() != Reloc::Static &&
468d2ef8c1fSFangrui Song       TheModule.getPIELevel() == PIELevel::Default;
469d2ef8c1fSFangrui Song 
4707c4a1a8dSMehdi Amini   if (!SingleModule) {
471d2ef8c1fSFangrui Song     promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);
4727c4a1a8dSMehdi Amini 
473e61652a3SPirama Arumuga Nainar     // Apply summary-based prevailing-symbol resolution decisions.
47420faf789Smodimo     thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);
4755a2e5d32SMehdi Amini 
4767c4a1a8dSMehdi Amini     // Save temps: after promotion.
4774b300e0aSMehdi Amini     saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");
478059464feSMehdi Amini   }
4797c4a1a8dSMehdi Amini 
4804d2613f2STeresa Johnson   // Be friendly and don't nuke totally the module when the client didn't
4814d2613f2STeresa Johnson   // supply anything to preserve.
4824d2613f2STeresa Johnson   if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {
4834d2613f2STeresa Johnson     // Apply summary-based internalization decisions.
4844d2613f2STeresa Johnson     thinLTOInternalizeModule(TheModule, DefinedGlobals);
4854d2613f2STeresa Johnson   }
486059464feSMehdi Amini 
487059464feSMehdi Amini   // Save internalized bitcode
4884b300e0aSMehdi Amini   saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");
489059464feSMehdi Amini 
490059464feSMehdi Amini   if (!SingleModule) {
491d2ef8c1fSFangrui Song     crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
492d2ef8c1fSFangrui Song                           ClearDSOLocalOnDeclarations);
4937c4a1a8dSMehdi Amini 
4947c4a1a8dSMehdi Amini     // Save temps: after cross-module import.
4954b300e0aSMehdi Amini     saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
4967c4a1a8dSMehdi Amini   }
4977c4a1a8dSMehdi Amini 
498ceadf6eeSNikita Popov   optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,
4998b8da01dSWael Yehia                  &Index);
5007c4a1a8dSMehdi Amini 
5014b300e0aSMehdi Amini   saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");
5027c4a1a8dSMehdi Amini 
50343b657b5SMehdi Amini   if (DisableCodeGen) {
50443b657b5SMehdi Amini     // Configured to stop before CodeGen, serialize the bitcode and return.
50543b657b5SMehdi Amini     SmallVector<char, 128> OutputBuffer;
50643b657b5SMehdi Amini     {
50743b657b5SMehdi Amini       raw_svector_ostream OS(OutputBuffer);
5085461d8bdSDehao Chen       ProfileSummaryInfo PSI(TheModule);
50994624acaSTeresa Johnson       auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);
5106a86e25dSRafael Espindola       WriteBitcodeToFile(TheModule, OS, true, &Index);
51143b657b5SMehdi Amini     }
512d0262c23SJan Svoboda     return std::make_unique<SmallVectorMemoryBuffer>(
513d0262c23SJan Svoboda         std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
51443b657b5SMehdi Amini   }
51543b657b5SMehdi Amini 
5167c4a1a8dSMehdi Amini   return codegenModule(TheModule, TM);
5177c4a1a8dSMehdi Amini }
5187c4a1a8dSMehdi Amini 
519e61652a3SPirama Arumuga Nainar /// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map
5204d2613f2STeresa Johnson /// for caching, and in the \p Index for application during the ThinLTO
5214d2613f2STeresa Johnson /// backends. This is needed for correctness for exported symbols (ensure
5224d2613f2STeresa Johnson /// at least one copy kept) and a compile-time optimization (to drop duplicate
5234d2613f2STeresa Johnson /// copies when possible).
resolvePrevailingInIndex(ModuleSummaryIndex & Index,StringMap<std::map<GlobalValue::GUID,GlobalValue::LinkageTypes>> & ResolvedODR,const DenseSet<GlobalValue::GUID> & GUIDPreservedSymbols,const DenseMap<GlobalValue::GUID,const GlobalValueSummary * > & PrevailingCopy)524e61652a3SPirama Arumuga Nainar static void resolvePrevailingInIndex(
5254d2613f2STeresa Johnson     ModuleSummaryIndex &Index,
5264d2613f2STeresa Johnson     StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>
52737b80122STeresa Johnson         &ResolvedODR,
528ea314fd4STeresa Johnson     const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
529ea314fd4STeresa Johnson     const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>
530ea314fd4STeresa Johnson         &PrevailingCopy) {
5314d2613f2STeresa Johnson 
5324d2613f2STeresa Johnson   auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
5334d2613f2STeresa Johnson     const auto &Prevailing = PrevailingCopy.find(GUID);
5344d2613f2STeresa Johnson     // Not in map means that there was only one copy, which must be prevailing.
5354d2613f2STeresa Johnson     if (Prevailing == PrevailingCopy.end())
5364d2613f2STeresa Johnson       return true;
5374d2613f2STeresa Johnson     return Prevailing->second == S;
5384d2613f2STeresa Johnson   };
5394d2613f2STeresa Johnson 
5404d2613f2STeresa Johnson   auto recordNewLinkage = [&](StringRef ModuleIdentifier,
5414d2613f2STeresa Johnson                               GlobalValue::GUID GUID,
5424d2613f2STeresa Johnson                               GlobalValue::LinkageTypes NewLinkage) {
5434d2613f2STeresa Johnson     ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
5444d2613f2STeresa Johnson   };
5454d2613f2STeresa Johnson 
54654fb3ca9SFangrui Song   // TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.
54754fb3ca9SFangrui Song   lto::Config Conf;
54854fb3ca9SFangrui Song   thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,
54937b80122STeresa Johnson                                   GUIDPreservedSymbols);
5504d2613f2STeresa Johnson }
5514d2613f2STeresa Johnson 
5527c4a1a8dSMehdi Amini // Initialize the TargetMachine builder for a given Triple
initTMBuilder(TargetMachineBuilder & TMBuilder,const Triple & TheTriple)5537c4a1a8dSMehdi Amini static void initTMBuilder(TargetMachineBuilder &TMBuilder,
5547c4a1a8dSMehdi Amini                           const Triple &TheTriple) {
5557c4a1a8dSMehdi Amini   // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
5567c4a1a8dSMehdi Amini   // FIXME this looks pretty terrible...
5577c4a1a8dSMehdi Amini   if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
5587c4a1a8dSMehdi Amini     if (TheTriple.getArch() == llvm::Triple::x86_64)
5597c4a1a8dSMehdi Amini       TMBuilder.MCpu = "core2";
5607c4a1a8dSMehdi Amini     else if (TheTriple.getArch() == llvm::Triple::x86)
5617c4a1a8dSMehdi Amini       TMBuilder.MCpu = "yonah";
562f1c28929STim Northover     else if (TheTriple.getArch() == llvm::Triple::aarch64 ||
563f1c28929STim Northover              TheTriple.getArch() == llvm::Triple::aarch64_32)
5647c4a1a8dSMehdi Amini       TMBuilder.MCpu = "cyclone";
5657c4a1a8dSMehdi Amini   }
5667c4a1a8dSMehdi Amini   TMBuilder.TheTriple = std::move(TheTriple);
5677c4a1a8dSMehdi Amini }
5687c4a1a8dSMehdi Amini 
5697c4a1a8dSMehdi Amini } // end anonymous namespace
5707c4a1a8dSMehdi Amini 
addModule(StringRef Identifier,StringRef Data)5717c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {
57205a358cdSSteven Wu   MemoryBufferRef Buffer(Data, Identifier);
573b10bff11SAkira Hatanaka 
57405a358cdSSteven Wu   auto InputOrError = lto::InputFile::create(Buffer);
57505a358cdSSteven Wu   if (!InputOrError)
57621661607SSimon Pilgrim     report_fatal_error(Twine("ThinLTO cannot create input file: ") +
57705a358cdSSteven Wu                        toString(InputOrError.takeError()));
578b10bff11SAkira Hatanaka 
57905a358cdSSteven Wu   auto TripleStr = (*InputOrError)->getTargetTriple();
580cd513a41SPeter Collingbourne   Triple TheTriple(TripleStr);
581b10bff11SAkira Hatanaka 
582b10bff11SAkira Hatanaka   if (Modules.empty())
5837c4a1a8dSMehdi Amini     initTMBuilder(TMBuilder, Triple(TheTriple));
584b10bff11SAkira Hatanaka   else if (TMBuilder.TheTriple != TheTriple) {
585b10bff11SAkira Hatanaka     if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
586b10bff11SAkira Hatanaka       report_fatal_error("ThinLTO modules with incompatible triples not "
587b10bff11SAkira Hatanaka                          "supported");
588b10bff11SAkira Hatanaka     initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
5897c4a1a8dSMehdi Amini   }
590b10bff11SAkira Hatanaka 
59105a358cdSSteven Wu   Modules.emplace_back(std::move(*InputOrError));
5927c4a1a8dSMehdi Amini }
5937c4a1a8dSMehdi Amini 
preserveSymbol(StringRef Name)5947c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {
5957c4a1a8dSMehdi Amini   PreservedSymbols.insert(Name);
5967c4a1a8dSMehdi Amini }
5977c4a1a8dSMehdi Amini 
crossReferenceSymbol(StringRef Name)5987c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {
5991380edf4SMehdi Amini   // FIXME: At the moment, we don't take advantage of this extra information,
6001380edf4SMehdi Amini   // we're conservatively considering cross-references as preserved.
6011380edf4SMehdi Amini   //  CrossReferencedSymbols.insert(Name);
6021380edf4SMehdi Amini   PreservedSymbols.insert(Name);
6037c4a1a8dSMehdi Amini }
6047c4a1a8dSMehdi Amini 
6057c4a1a8dSMehdi Amini // TargetMachine factory
create() const6067c4a1a8dSMehdi Amini std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
6077c4a1a8dSMehdi Amini   std::string ErrMsg;
6087c4a1a8dSMehdi Amini   const Target *TheTarget =
6097c4a1a8dSMehdi Amini       TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);
6107c4a1a8dSMehdi Amini   if (!TheTarget) {
61121661607SSimon Pilgrim     report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);
6127c4a1a8dSMehdi Amini   }
6137c4a1a8dSMehdi Amini 
6147c4a1a8dSMehdi Amini   // Use MAttr as the default set of features.
6157c4a1a8dSMehdi Amini   SubtargetFeatures Features(MAttr);
6167c4a1a8dSMehdi Amini   Features.getDefaultSubtargetFeatures(TheTriple);
6177c4a1a8dSMehdi Amini   std::string FeatureStr = Features.getString();
618cc7fbf71SMehdi Amini 
6191756d679SElla Ma   std::unique_ptr<TargetMachine> TM(
62079e238afSRafael Espindola       TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
62179e238afSRafael Espindola                                      RelocModel, None, CGOptLevel));
6221756d679SElla Ma   assert(TM && "Cannot create target machine");
6231756d679SElla Ma 
6241756d679SElla Ma   return TM;
6257c4a1a8dSMehdi Amini }
6267c4a1a8dSMehdi Amini 
6277c4a1a8dSMehdi Amini /**
62826ab5772STeresa Johnson  * Produce the combined summary index from all the bitcode files:
6297c4a1a8dSMehdi Amini  * "thin-link".
6307c4a1a8dSMehdi Amini  */
linkCombinedIndex()63126ab5772STeresa Johnson std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
63274d22dd7SPeter Collingbourne   std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
6330eaee545SJonas Devlieghere       std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
6347c4a1a8dSMehdi Amini   uint64_t NextModuleId = 0;
63505a358cdSSteven Wu   for (auto &Mod : Modules) {
63605a358cdSSteven Wu     auto &M = Mod->getSingleBitcodeModule();
63705a358cdSSteven Wu     if (Error Err =
63805a358cdSSteven Wu             M.readSummary(*CombinedIndex, Mod->getName(), NextModuleId++)) {
6397c4a1a8dSMehdi Amini       // FIXME diagnose
6406de481a3SPeter Collingbourne       logAllUnhandledErrors(
64174d22dd7SPeter Collingbourne           std::move(Err), errs(),
642c15d60b7SPeter Collingbourne           "error: can't create module summary index for buffer: ");
6437c4a1a8dSMehdi Amini       return nullptr;
6447c4a1a8dSMehdi Amini     }
6457c4a1a8dSMehdi Amini   }
6467c4a1a8dSMehdi Amini   return CombinedIndex;
6477c4a1a8dSMehdi Amini }
6487c4a1a8dSMehdi Amini 
649bfa3f0c3SBenjamin Kramer namespace {
650eb34c3e8SEugene Leviant struct IsExported {
651eb34c3e8SEugene Leviant   const StringMap<FunctionImporter::ExportSetTy> &ExportLists;
652eb34c3e8SEugene Leviant   const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;
653eb34c3e8SEugene Leviant 
IsExported__anon39b237c20e11::IsExported654eb34c3e8SEugene Leviant   IsExported(const StringMap<FunctionImporter::ExportSetTy> &ExportLists,
655eb34c3e8SEugene Leviant              const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)
656eb34c3e8SEugene Leviant       : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}
657eb34c3e8SEugene Leviant 
operator ()__anon39b237c20e11::IsExported6583d708bf5Sevgeny   bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {
6592421b6faSGeorge Rimar     const auto &ExportList = ExportLists.find(ModuleIdentifier);
6603d708bf5Sevgeny     return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||
6613d708bf5Sevgeny            GUIDPreservedSymbols.count(VI.getGUID());
662eb34c3e8SEugene Leviant   }
6632421b6faSGeorge Rimar };
6642421b6faSGeorge Rimar 
665eb34c3e8SEugene Leviant struct IsPrevailing {
666eb34c3e8SEugene Leviant   const DenseMap<GlobalValue::GUID, const GlobalValueSummary *> &PrevailingCopy;
IsPrevailing__anon39b237c20e11::IsPrevailing667eb34c3e8SEugene Leviant   IsPrevailing(const DenseMap<GlobalValue::GUID, const GlobalValueSummary *>
668eb34c3e8SEugene Leviant                    &PrevailingCopy)
669eb34c3e8SEugene Leviant       : PrevailingCopy(PrevailingCopy) {}
670eb34c3e8SEugene Leviant 
operator ()__anon39b237c20e11::IsPrevailing671eb34c3e8SEugene Leviant   bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {
672ea314fd4STeresa Johnson     const auto &Prevailing = PrevailingCopy.find(GUID);
673ea314fd4STeresa Johnson     // Not in map means that there was only one copy, which must be prevailing.
674ea314fd4STeresa Johnson     if (Prevailing == PrevailingCopy.end())
675ea314fd4STeresa Johnson       return true;
676ea314fd4STeresa Johnson     return Prevailing->second == S;
677ea314fd4STeresa Johnson   };
678eb34c3e8SEugene Leviant };
679950b800cSMichael Liao } // namespace
6802421b6faSGeorge Rimar 
computeDeadSymbolsInIndex(ModuleSummaryIndex & Index,const DenseSet<GlobalValue::GUID> & GUIDPreservedSymbols)681eaf5172cSGeorge Rimar static void computeDeadSymbolsInIndex(
682eaf5172cSGeorge Rimar     ModuleSummaryIndex &Index,
683eaf5172cSGeorge Rimar     const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
684eaf5172cSGeorge Rimar   // We have no symbols resolution available. And can't do any better now in the
685eaf5172cSGeorge Rimar   // case where the prevailing symbol is in a native object. It can be refined
686eaf5172cSGeorge Rimar   // with linker information in the future.
687eaf5172cSGeorge Rimar   auto isPrevailing = [&](GlobalValue::GUID G) {
688eaf5172cSGeorge Rimar     return PrevailingType::Unknown;
689eaf5172cSGeorge Rimar   };
690bf46e741SEugene Leviant   computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,
691bf46e741SEugene Leviant                                   /* ImportEnabled = */ true);
692eaf5172cSGeorge Rimar }
693eaf5172cSGeorge Rimar 
6947c4a1a8dSMehdi Amini /**
6957c4a1a8dSMehdi Amini  * Perform promotion and renaming of exported internal functions.
6964d2613f2STeresa Johnson  * Index is updated to reflect linkage changes from weak resolution.
6977c4a1a8dSMehdi Amini  */
promote(Module & TheModule,ModuleSummaryIndex & Index,const lto::InputFile & File)69805a358cdSSteven Wu void ThinLTOCodeGenerator::promote(Module &TheModule, ModuleSummaryIndex &Index,
69905a358cdSSteven Wu                                    const lto::InputFile &File) {
700a71a5a62SMehdi Amini   auto ModuleCount = Index.modulePaths().size();
7011aafabf7SMehdi Amini   auto ModuleIdentifier = TheModule.getModuleIdentifier();
7024fef68cbSTeresa Johnson 
7031aafabf7SMehdi Amini   // Collect for each module the list of function it defines (GUID -> Summary).
704c851d216STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
7051aafabf7SMehdi Amini   Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
7065a2e5d32SMehdi Amini 
7076c475a75STeresa Johnson   // Convert the preserved symbols set from string to GUID
7081380edf4SMehdi Amini   auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
70934b289b6SSteven Wu       File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
7106c475a75STeresa Johnson 
71105a358cdSSteven Wu   // Add used symbol to the preserved symbols.
71205a358cdSSteven Wu   addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
71305a358cdSSteven Wu 
7146c475a75STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
715eaf5172cSGeorge Rimar   computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
7166c475a75STeresa Johnson 
717a71a5a62SMehdi Amini   // Generate import/export list
718a71a5a62SMehdi Amini   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
719a71a5a62SMehdi Amini   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
720a71a5a62SMehdi Amini   ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
72156584bbfSEvgeniy Stepanov                            ExportLists);
722a71a5a62SMehdi Amini 
723ea314fd4STeresa Johnson   DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
724ea314fd4STeresa Johnson   computePrevailingCopies(Index, PrevailingCopy);
725ea314fd4STeresa Johnson 
726e61652a3SPirama Arumuga Nainar   // Resolve prevailing symbols
7274d2613f2STeresa Johnson   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
728ea314fd4STeresa Johnson   resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
729ea314fd4STeresa Johnson                            PrevailingCopy);
7304d2613f2STeresa Johnson 
73120faf789Smodimo   thinLTOFinalizeInModule(TheModule,
73220faf789Smodimo                           ModuleToDefinedGVSummaries[ModuleIdentifier],
73320faf789Smodimo                           /*PropagateAttrs=*/false);
734f41e70d6SSteven Wu 
7354fef68cbSTeresa Johnson   // Promote the exported values in the index, so that they are promoted
7364fef68cbSTeresa Johnson   // in the module.
737eb34c3e8SEugene Leviant   thinLTOInternalizeAndPromoteInIndex(
738eb34c3e8SEugene Leviant       Index, IsExported(ExportLists, GUIDPreservedSymbols),
739eb34c3e8SEugene Leviant       IsPrevailing(PrevailingCopy));
7404fef68cbSTeresa Johnson 
741d2ef8c1fSFangrui Song   // FIXME Set ClearDSOLocalOnDeclarations.
742d2ef8c1fSFangrui Song   promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
7437c4a1a8dSMehdi Amini }
7447c4a1a8dSMehdi Amini 
7457c4a1a8dSMehdi Amini /**
7467c4a1a8dSMehdi Amini  * Perform cross-module importing for the module identified by ModuleIdentifier.
7477c4a1a8dSMehdi Amini  */
crossModuleImport(Module & TheModule,ModuleSummaryIndex & Index,const lto::InputFile & File)7487c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
74905a358cdSSteven Wu                                              ModuleSummaryIndex &Index,
75005a358cdSSteven Wu                                              const lto::InputFile &File) {
7517c4a1a8dSMehdi Amini   auto ModuleMap = generateModuleMap(Modules);
7521aafabf7SMehdi Amini   auto ModuleCount = Index.modulePaths().size();
7531aafabf7SMehdi Amini 
7541aafabf7SMehdi Amini   // Collect for each module the list of function it defines (GUID -> Summary).
755c851d216STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
7561aafabf7SMehdi Amini   Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
75701e32130SMehdi Amini 
7586c475a75STeresa Johnson   // Convert the preserved symbols set from string to GUID
7591380edf4SMehdi Amini   auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
76034b289b6SSteven Wu       File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
7616c475a75STeresa Johnson 
76205a358cdSSteven Wu   addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
76305a358cdSSteven Wu 
7646c475a75STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
765eaf5172cSGeorge Rimar   computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
7666c475a75STeresa Johnson 
76701e32130SMehdi Amini   // Generate import/export list
76801e32130SMehdi Amini   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
76901e32130SMehdi Amini   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
7701aafabf7SMehdi Amini   ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
77156584bbfSEvgeniy Stepanov                            ExportLists);
77201e32130SMehdi Amini   auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
77301e32130SMehdi Amini 
774d2ef8c1fSFangrui Song   // FIXME Set ClearDSOLocalOnDeclarations.
775d2ef8c1fSFangrui Song   crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
776d2ef8c1fSFangrui Song                         /*ClearDSOLocalOnDeclarations=*/false);
7777c4a1a8dSMehdi Amini }
7787c4a1a8dSMehdi Amini 
7797c4a1a8dSMehdi Amini /**
78084174c37STeresa Johnson  * Compute the list of summaries needed for importing into module.
78184174c37STeresa Johnson  */
gatherImportedSummariesForModule(Module & TheModule,ModuleSummaryIndex & Index,std::map<std::string,GVSummaryMapTy> & ModuleToSummariesForIndex,const lto::InputFile & File)78284174c37STeresa Johnson void ThinLTOCodeGenerator::gatherImportedSummariesForModule(
78393f99962STeresa Johnson     Module &TheModule, ModuleSummaryIndex &Index,
78405a358cdSSteven Wu     std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
78505a358cdSSteven Wu     const lto::InputFile &File) {
78684174c37STeresa Johnson   auto ModuleCount = Index.modulePaths().size();
78793f99962STeresa Johnson   auto ModuleIdentifier = TheModule.getModuleIdentifier();
78884174c37STeresa Johnson 
78984174c37STeresa Johnson   // Collect for each module the list of function it defines (GUID -> Summary).
79084174c37STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
79184174c37STeresa Johnson   Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
79284174c37STeresa Johnson 
79393f99962STeresa Johnson   // Convert the preserved symbols set from string to GUID
79493f99962STeresa Johnson   auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
79534b289b6SSteven Wu       File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
79693f99962STeresa Johnson 
79705a358cdSSteven Wu   addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
79805a358cdSSteven Wu 
79993f99962STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
80093f99962STeresa Johnson   computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
80193f99962STeresa Johnson 
80284174c37STeresa Johnson   // Generate import/export list
80384174c37STeresa Johnson   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
80484174c37STeresa Johnson   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
80584174c37STeresa Johnson   ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
80684174c37STeresa Johnson                            ExportLists);
80784174c37STeresa Johnson 
80893f99962STeresa Johnson   llvm::gatherImportedSummariesForModule(
80993f99962STeresa Johnson       ModuleIdentifier, ModuleToDefinedGVSummaries,
81093f99962STeresa Johnson       ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
81184174c37STeresa Johnson }
81284174c37STeresa Johnson 
81384174c37STeresa Johnson /**
8148570fe47STeresa Johnson  * Emit the list of files needed for importing into module.
8158570fe47STeresa Johnson  */
emitImports(Module & TheModule,StringRef OutputName,ModuleSummaryIndex & Index,const lto::InputFile & File)81693f99962STeresa Johnson void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName,
81705a358cdSSteven Wu                                        ModuleSummaryIndex &Index,
81805a358cdSSteven Wu                                        const lto::InputFile &File) {
8198570fe47STeresa Johnson   auto ModuleCount = Index.modulePaths().size();
82093f99962STeresa Johnson   auto ModuleIdentifier = TheModule.getModuleIdentifier();
8218570fe47STeresa Johnson 
8228570fe47STeresa Johnson   // Collect for each module the list of function it defines (GUID -> Summary).
8238570fe47STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
8248570fe47STeresa Johnson   Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
8258570fe47STeresa Johnson 
82693f99962STeresa Johnson   // Convert the preserved symbols set from string to GUID
82793f99962STeresa Johnson   auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
82834b289b6SSteven Wu       File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
82993f99962STeresa Johnson 
83005a358cdSSteven Wu   addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
83105a358cdSSteven Wu 
83293f99962STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
83393f99962STeresa Johnson   computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
83493f99962STeresa Johnson 
8358570fe47STeresa Johnson   // Generate import/export list
8368570fe47STeresa Johnson   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
8378570fe47STeresa Johnson   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
8388570fe47STeresa Johnson   ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
8398570fe47STeresa Johnson                            ExportLists);
8408570fe47STeresa Johnson 
841c0320ef4STeresa Johnson   std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
84293f99962STeresa Johnson   llvm::gatherImportedSummariesForModule(
84393f99962STeresa Johnson       ModuleIdentifier, ModuleToDefinedGVSummaries,
84493f99962STeresa Johnson       ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
845c0320ef4STeresa Johnson 
8468570fe47STeresa Johnson   std::error_code EC;
84793f99962STeresa Johnson   if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
84893f99962STeresa Johnson                              ModuleToSummariesForIndex)))
8498570fe47STeresa Johnson     report_fatal_error(Twine("Failed to open ") + OutputName +
8508570fe47STeresa Johnson                        " to save imports lists\n");
8518570fe47STeresa Johnson }
8528570fe47STeresa Johnson 
8538570fe47STeresa Johnson /**
85405a358cdSSteven Wu  * Perform internalization. Runs promote and internalization together.
85505a358cdSSteven Wu  * Index is updated to reflect linkage changes.
856059464feSMehdi Amini  */
internalize(Module & TheModule,ModuleSummaryIndex & Index,const lto::InputFile & File)857059464feSMehdi Amini void ThinLTOCodeGenerator::internalize(Module &TheModule,
85805a358cdSSteven Wu                                        ModuleSummaryIndex &Index,
85905a358cdSSteven Wu                                        const lto::InputFile &File) {
860059464feSMehdi Amini   initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
861059464feSMehdi Amini   auto ModuleCount = Index.modulePaths().size();
862059464feSMehdi Amini   auto ModuleIdentifier = TheModule.getModuleIdentifier();
863059464feSMehdi Amini 
864059464feSMehdi Amini   // Convert the preserved symbols set from string to GUID
865059464feSMehdi Amini   auto GUIDPreservedSymbols =
86634b289b6SSteven Wu       computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);
867059464feSMehdi Amini 
86805a358cdSSteven Wu   addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
86905a358cdSSteven Wu 
870059464feSMehdi Amini   // Collect for each module the list of function it defines (GUID -> Summary).
871c851d216STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
872059464feSMehdi Amini   Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
873059464feSMehdi Amini 
8746c475a75STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
875eaf5172cSGeorge Rimar   computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
8766c475a75STeresa Johnson 
877059464feSMehdi Amini   // Generate import/export list
878059464feSMehdi Amini   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
879059464feSMehdi Amini   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
880059464feSMehdi Amini   ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
88156584bbfSEvgeniy Stepanov                            ExportLists);
882059464feSMehdi Amini   auto &ExportList = ExportLists[ModuleIdentifier];
883059464feSMehdi Amini 
8844d2613f2STeresa Johnson   // Be friendly and don't nuke totally the module when the client didn't
8854d2613f2STeresa Johnson   // supply anything to preserve.
8864d2613f2STeresa Johnson   if (ExportList.empty() && GUIDPreservedSymbols.empty())
8874d2613f2STeresa Johnson     return;
8884d2613f2STeresa Johnson 
889ea314fd4STeresa Johnson   DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
890ea314fd4STeresa Johnson   computePrevailingCopies(Index, PrevailingCopy);
891ea314fd4STeresa Johnson 
89205a358cdSSteven Wu   // Resolve prevailing symbols
89305a358cdSSteven Wu   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
894ea314fd4STeresa Johnson   resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
895ea314fd4STeresa Johnson                            PrevailingCopy);
89605a358cdSSteven Wu 
89705a358cdSSteven Wu   // Promote the exported values in the index, so that they are promoted
89805a358cdSSteven Wu   // in the module.
899eb34c3e8SEugene Leviant   thinLTOInternalizeAndPromoteInIndex(
900eb34c3e8SEugene Leviant       Index, IsExported(ExportLists, GUIDPreservedSymbols),
901eb34c3e8SEugene Leviant       IsPrevailing(PrevailingCopy));
90205a358cdSSteven Wu 
903d2ef8c1fSFangrui Song   // FIXME Set ClearDSOLocalOnDeclarations.
904d2ef8c1fSFangrui Song   promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
90505a358cdSSteven Wu 
90605a358cdSSteven Wu   // Internalization
90720faf789Smodimo   thinLTOFinalizeInModule(TheModule,
90820faf789Smodimo                           ModuleToDefinedGVSummaries[ModuleIdentifier],
90920faf789Smodimo                           /*PropagateAttrs=*/false);
91005a358cdSSteven Wu 
9114d2613f2STeresa Johnson   thinLTOInternalizeModule(TheModule,
9124d2613f2STeresa Johnson                            ModuleToDefinedGVSummaries[ModuleIdentifier]);
913059464feSMehdi Amini }
914059464feSMehdi Amini 
915059464feSMehdi Amini /**
9167c4a1a8dSMehdi Amini  * Perform post-importing ThinLTO optimizations.
9177c4a1a8dSMehdi Amini  */
optimize(Module & TheModule)9187c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::optimize(Module &TheModule) {
9197c4a1a8dSMehdi Amini   initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
920059464feSMehdi Amini 
921059464feSMehdi Amini   // Optimize now
922eb34c3e8SEugene Leviant   optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
923ceadf6eeSNikita Popov                  DebugPassManager, nullptr);
9247c4a1a8dSMehdi Amini }
9257c4a1a8dSMehdi Amini 
9268e13bc45SMehdi Amini /// Write out the generated object file, either from CacheEntryPath or from
9278e13bc45SMehdi Amini /// OutputBuffer, preferring hard-link when possible.
9288e13bc45SMehdi Amini /// Returns the path to the generated file in SavedObjectsDirectoryPath.
9296c9f6fd1SSteven Wu std::string
writeGeneratedObject(int count,StringRef CacheEntryPath,const MemoryBuffer & OutputBuffer)9306c9f6fd1SSteven Wu ThinLTOCodeGenerator::writeGeneratedObject(int count, StringRef CacheEntryPath,
9318e13bc45SMehdi Amini                                            const MemoryBuffer &OutputBuffer) {
9326c9f6fd1SSteven Wu   auto ArchName = TMBuilder.TheTriple.getArchName();
9338e13bc45SMehdi Amini   SmallString<128> OutputPath(SavedObjectsDirectoryPath);
9346c9f6fd1SSteven Wu   llvm::sys::path::append(OutputPath,
9356c9f6fd1SSteven Wu                           Twine(count) + "." + ArchName + ".thinlto.o");
9368e13bc45SMehdi Amini   OutputPath.c_str(); // Ensure the string is null terminated.
9378e13bc45SMehdi Amini   if (sys::fs::exists(OutputPath))
9388e13bc45SMehdi Amini     sys::fs::remove(OutputPath);
9398e13bc45SMehdi Amini 
9408e13bc45SMehdi Amini   // We don't return a memory buffer to the linker, just a list of files.
9418e13bc45SMehdi Amini   if (!CacheEntryPath.empty()) {
9428e13bc45SMehdi Amini     // Cache is enabled, hard-link the entry (or copy if hard-link fails).
9438e13bc45SMehdi Amini     auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);
9448e13bc45SMehdi Amini     if (!Err)
945adcd0268SBenjamin Kramer       return std::string(OutputPath.str());
9468e13bc45SMehdi Amini     // Hard linking failed, try to copy.
9478e13bc45SMehdi Amini     Err = sys::fs::copy_file(CacheEntryPath, OutputPath);
9488e13bc45SMehdi Amini     if (!Err)
949adcd0268SBenjamin Kramer       return std::string(OutputPath.str());
9508e13bc45SMehdi Amini     // Copy failed (could be because the CacheEntry was removed from the cache
9518e13bc45SMehdi Amini     // in the meantime by another process), fall back and try to write down the
9528e13bc45SMehdi Amini     // buffer to the output.
953d7fad626Sromanova-ekaterina     errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath
9548e13bc45SMehdi Amini            << "' to '" << OutputPath << "'\n";
9558e13bc45SMehdi Amini   }
9568e13bc45SMehdi Amini   // No cache entry, just write out the buffer.
9578e13bc45SMehdi Amini   std::error_code Err;
958d9b948b6SFangrui Song   raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);
9598e13bc45SMehdi Amini   if (Err)
96021661607SSimon Pilgrim     report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");
9618e13bc45SMehdi Amini   OS << OutputBuffer.getBuffer();
962adcd0268SBenjamin Kramer   return std::string(OutputPath.str());
9638e13bc45SMehdi Amini }
9648e13bc45SMehdi Amini 
9657c4a1a8dSMehdi Amini // Main entry point for the ThinLTO processing
run()9667c4a1a8dSMehdi Amini void ThinLTOCodeGenerator::run() {
967f5b8a312Smodimo   timeTraceProfilerBegin("ThinLink", StringRef(""));
968f5b8a312Smodimo   auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
969f5b8a312Smodimo     if (llvm::timeTraceProfilerEnabled())
970f5b8a312Smodimo       llvm::timeTraceProfilerEnd();
971f5b8a312Smodimo   });
972b2990466SMehdi Amini   // Prepare the resulting object vector
973b2990466SMehdi Amini   assert(ProducedBinaries.empty() && "The generator should not be reused");
974b2990466SMehdi Amini   if (SavedObjectsDirectoryPath.empty())
975b2990466SMehdi Amini     ProducedBinaries.resize(Modules.size());
976b2990466SMehdi Amini   else {
977b2990466SMehdi Amini     sys::fs::create_directories(SavedObjectsDirectoryPath);
978b2990466SMehdi Amini     bool IsDir;
979b2990466SMehdi Amini     sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
980b2990466SMehdi Amini     if (!IsDir)
98121661607SSimon Pilgrim       report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");
982b2990466SMehdi Amini     ProducedBinaryFiles.resize(Modules.size());
983b2990466SMehdi Amini   }
984b2990466SMehdi Amini 
98543b657b5SMehdi Amini   if (CodeGenOnly) {
98643b657b5SMehdi Amini     // Perform only parallel codegen and return.
98743b657b5SMehdi Amini     ThreadPool Pool;
98843b657b5SMehdi Amini     int count = 0;
98905a358cdSSteven Wu     for (auto &Mod : Modules) {
99043b657b5SMehdi Amini       Pool.async([&](int count) {
99143b657b5SMehdi Amini         LLVMContext Context;
99243b657b5SMehdi Amini         Context.setDiscardValueNames(LTODiscardValueNames);
99343b657b5SMehdi Amini 
99443b657b5SMehdi Amini         // Parse module now
99505a358cdSSteven Wu         auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
996a61f5e37STeresa Johnson                                              /*IsImporting*/ false);
99743b657b5SMehdi Amini 
99843b657b5SMehdi Amini         // CodeGen
999cf90203bSSteven Wu         auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
1000b2990466SMehdi Amini         if (SavedObjectsDirectoryPath.empty())
1001b2990466SMehdi Amini           ProducedBinaries[count] = std::move(OutputBuffer);
1002b2990466SMehdi Amini         else
10036c9f6fd1SSteven Wu           ProducedBinaryFiles[count] =
10046c9f6fd1SSteven Wu               writeGeneratedObject(count, "", *OutputBuffer);
100543b657b5SMehdi Amini       }, count++);
100643b657b5SMehdi Amini     }
100743b657b5SMehdi Amini 
100843b657b5SMehdi Amini     return;
100943b657b5SMehdi Amini   }
101043b657b5SMehdi Amini 
10117c4a1a8dSMehdi Amini   // Sequential linking phase
10127c4a1a8dSMehdi Amini   auto Index = linkCombinedIndex();
10137c4a1a8dSMehdi Amini 
10147c4a1a8dSMehdi Amini   // Save temps: index.
10157c4a1a8dSMehdi Amini   if (!SaveTempsDir.empty()) {
10167c4a1a8dSMehdi Amini     auto SaveTempPath = SaveTempsDir + "index.bc";
10177c4a1a8dSMehdi Amini     std::error_code EC;
1018d9b948b6SFangrui Song     raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
10197c4a1a8dSMehdi Amini     if (EC)
10207c4a1a8dSMehdi Amini       report_fatal_error(Twine("Failed to open ") + SaveTempPath +
10217c4a1a8dSMehdi Amini                          " to save optimized bitcode\n");
10227aaf024dSFangrui Song     writeIndexToFile(*Index, OS);
10237c4a1a8dSMehdi Amini   }
10247c4a1a8dSMehdi Amini 
10257c4a1a8dSMehdi Amini 
10267c4a1a8dSMehdi Amini   // Prepare the module map.
10277c4a1a8dSMehdi Amini   auto ModuleMap = generateModuleMap(Modules);
102801e32130SMehdi Amini   auto ModuleCount = Modules.size();
102901e32130SMehdi Amini 
10301aafabf7SMehdi Amini   // Collect for each module the list of function it defines (GUID -> Summary).
1031c851d216STeresa Johnson   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
10321aafabf7SMehdi Amini   Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
10331aafabf7SMehdi Amini 
10346c475a75STeresa Johnson   // Convert the preserved symbols set from string to GUID, this is needed for
10356c475a75STeresa Johnson   // computing the caching hash and the internalization.
103634b289b6SSteven Wu   DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
103734b289b6SSteven Wu   for (const auto &M : Modules)
103834b289b6SSteven Wu     computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,
103934b289b6SSteven Wu                                 GUIDPreservedSymbols);
10406c475a75STeresa Johnson 
104105a358cdSSteven Wu   // Add used symbol from inputs to the preserved symbols.
104205a358cdSSteven Wu   for (const auto &M : Modules)
104305a358cdSSteven Wu     addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
104405a358cdSSteven Wu 
10456c475a75STeresa Johnson   // Compute "dead" symbols, we don't want to import/export these!
1046eaf5172cSGeorge Rimar   computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
10476c475a75STeresa Johnson 
10485a7056faSEaswaran Raman   // Synthesize entry counts for functions in the combined index.
10495a7056faSEaswaran Raman   computeSyntheticCounts(*Index);
10505a7056faSEaswaran Raman 
10512f63d549STeresa Johnson   // Currently there is no support for enabling whole program visibility via a
10522f63d549STeresa Johnson   // linker option in the old LTO API, but this call allows it to be specified
10532f63d549STeresa Johnson   // via the internal option. Must be done before WPD below.
1054*2eade1dbSArthur Eubanks   if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))
1055*2eade1dbSArthur Eubanks     Index->setWithWholeProgramVisibility();
10562f63d549STeresa Johnson   updateVCallVisibilityInIndex(*Index,
10571487747eSTeresa Johnson                                /* WholeProgramVisibilityEnabledInLTO */ false,
10581487747eSTeresa Johnson                                // FIXME: This needs linker information via a
10591487747eSTeresa Johnson                                // TBD new interface.
10601487747eSTeresa Johnson                                /* DynamicExportSymbols */ {});
10612f63d549STeresa Johnson 
1062eb34c3e8SEugene Leviant   // Perform index-based WPD. This will return immediately if there are
1063eb34c3e8SEugene Leviant   // no index entries in the typeIdMetadata map (e.g. if we are instead
1064eb34c3e8SEugene Leviant   // performing IR-based WPD in hybrid regular/thin LTO mode).
1065eb34c3e8SEugene Leviant   std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1066eb34c3e8SEugene Leviant   std::set<GlobalValue::GUID> ExportedGUIDs;
1067eb34c3e8SEugene Leviant   runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);
1068eb34c3e8SEugene Leviant   for (auto GUID : ExportedGUIDs)
1069eb34c3e8SEugene Leviant     GUIDPreservedSymbols.insert(GUID);
1070eb34c3e8SEugene Leviant 
107101e32130SMehdi Amini   // Collect the import/export lists for all modules from the call-graph in the
107201e32130SMehdi Amini   // combined index.
107301e32130SMehdi Amini   StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
107401e32130SMehdi Amini   StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
10751aafabf7SMehdi Amini   ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists,
107656584bbfSEvgeniy Stepanov                            ExportLists);
1077f95f77adSMehdi Amini 
10784d2613f2STeresa Johnson   // We use a std::map here to be able to have a defined ordering when
10794d2613f2STeresa Johnson   // producing a hash for the cache entry.
10804d2613f2STeresa Johnson   // FIXME: we should be able to compute the caching hash for the entry based
10814d2613f2STeresa Johnson   // on the index, and nuke this map.
10824d2613f2STeresa Johnson   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
10834d2613f2STeresa Johnson 
1084ea314fd4STeresa Johnson   DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1085ea314fd4STeresa Johnson   computePrevailingCopies(*Index, PrevailingCopy);
1086ea314fd4STeresa Johnson 
1087e61652a3SPirama Arumuga Nainar   // Resolve prevailing symbols, this has to be computed early because it
10884d2613f2STeresa Johnson   // impacts the caching.
1089ea314fd4STeresa Johnson   resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,
1090ea314fd4STeresa Johnson                            PrevailingCopy);
10914d2613f2STeresa Johnson 
10924d2613f2STeresa Johnson   // Use global summary-based analysis to identify symbols that can be
10934d2613f2STeresa Johnson   // internalized (because they aren't exported or preserved as per callback).
10944d2613f2STeresa Johnson   // Changes are made in the index, consumed in the ThinLTO backends.
1095eb34c3e8SEugene Leviant   updateIndexWPDForExports(*Index,
1096eb34c3e8SEugene Leviant                            IsExported(ExportLists, GUIDPreservedSymbols),
1097eb34c3e8SEugene Leviant                            LocalWPDTargetsMap);
1098eb34c3e8SEugene Leviant   thinLTOInternalizeAndPromoteInIndex(
1099eb34c3e8SEugene Leviant       *Index, IsExported(ExportLists, GUIDPreservedSymbols),
1100eb34c3e8SEugene Leviant       IsPrevailing(PrevailingCopy));
11014d2613f2STeresa Johnson 
110220faf789Smodimo   thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));
110320faf789Smodimo 
1104ec53c89fSSteven Wu   // Make sure that every module has an entry in the ExportLists, ImportList,
1105ec53c89fSSteven Wu   // GVSummary and ResolvedODR maps to enable threaded access to these maps
1106ec53c89fSSteven Wu   // below.
1107ec53c89fSSteven Wu   for (auto &Module : Modules) {
110805a358cdSSteven Wu     auto ModuleIdentifier = Module->getName();
1109ec53c89fSSteven Wu     ExportLists[ModuleIdentifier];
1110ec53c89fSSteven Wu     ImportLists[ModuleIdentifier];
1111ec53c89fSSteven Wu     ResolvedODR[ModuleIdentifier];
1112ec53c89fSSteven Wu     ModuleToDefinedGVSummaries[ModuleIdentifier];
1113141149ffSTeresa Johnson   }
1114af52f28dSMehdi Amini 
1115617d64f6SAlexandre Ganea   std::vector<BitcodeModule *> ModulesVec;
1116617d64f6SAlexandre Ganea   ModulesVec.reserve(Modules.size());
1117617d64f6SAlexandre Ganea   for (auto &Mod : Modules)
1118617d64f6SAlexandre Ganea     ModulesVec.push_back(&Mod->getSingleBitcodeModule());
1119617d64f6SAlexandre Ganea   std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);
1120819e9cdfSMehdi Amini 
1121f5b8a312Smodimo   if (llvm::timeTraceProfilerEnabled())
1122f5b8a312Smodimo     llvm::timeTraceProfilerEnd();
1123f5b8a312Smodimo 
1124f5b8a312Smodimo   TimeTraceScopeExit.release();
1125f5b8a312Smodimo 
11267c4a1a8dSMehdi Amini   // Parallel optimizer + codegen
11277c4a1a8dSMehdi Amini   {
11288404aeb5SAlexandre Ganea     ThreadPool Pool(heavyweight_hardware_concurrency(ThreadCount));
1129819e9cdfSMehdi Amini     for (auto IndexCount : ModulesOrdering) {
113005a358cdSSteven Wu       auto &Mod = Modules[IndexCount];
11317c4a1a8dSMehdi Amini       Pool.async([&](int count) {
113205a358cdSSteven Wu         auto ModuleIdentifier = Mod->getName();
1133a71a5a62SMehdi Amini         auto &ExportList = ExportLists[ModuleIdentifier];
11341aafabf7SMehdi Amini 
1135bf46e741SEugene Leviant         auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
1136f95f77adSMehdi Amini 
1137f95f77adSMehdi Amini         // The module may be cached, this helps handling it.
1138059464feSMehdi Amini         ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,
1139059464feSMehdi Amini                                     ImportLists[ModuleIdentifier], ExportList,
11404d2613f2STeresa Johnson                                     ResolvedODR[ModuleIdentifier],
11415f312ad4STeresa Johnson                                     DefinedGVSummaries, OptLevel, Freestanding,
11425f312ad4STeresa Johnson                                     TMBuilder);
11438e13bc45SMehdi Amini         auto CacheEntryPath = CacheEntry.getEntryPath();
1144f95f77adSMehdi Amini 
1145f95f77adSMehdi Amini         {
1146f95f77adSMehdi Amini           auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
1147d34e60caSNicola Zaghen           LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
1148d34e60caSNicola Zaghen                             << " '" << CacheEntryPath << "' for buffer "
1149d34e60caSNicola Zaghen                             << count << " " << ModuleIdentifier << "\n");
1150059464feSMehdi Amini 
1151f95f77adSMehdi Amini           if (ErrOrBuffer) {
1152f95f77adSMehdi Amini             // Cache Hit!
11538e13bc45SMehdi Amini             if (SavedObjectsDirectoryPath.empty())
1154f95f77adSMehdi Amini               ProducedBinaries[count] = std::move(ErrOrBuffer.get());
11558e13bc45SMehdi Amini             else
11568e13bc45SMehdi Amini               ProducedBinaryFiles[count] = writeGeneratedObject(
11576c9f6fd1SSteven Wu                   count, CacheEntryPath, *ErrOrBuffer.get());
1158f95f77adSMehdi Amini             return;
1159f95f77adSMehdi Amini           }
1160f95f77adSMehdi Amini         }
1161f95f77adSMehdi Amini 
1162f95f77adSMehdi Amini         LLVMContext Context;
1163f95f77adSMehdi Amini         Context.setDiscardValueNames(LTODiscardValueNames);
1164f95f77adSMehdi Amini         Context.enableDebugTypeODRUniquing();
11657531a503SFrancis Visoiu Mistrih         auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
116634667519SFrancis Visoiu Mistrih             Context, RemarksFilename, RemarksPasses, RemarksFormat,
11673acda917SWei Wang             RemarksWithHotness, RemarksHotnessThreshold, count);
116819f176b9SMehdi Amini         if (!DiagFileOrErr) {
116919f176b9SMehdi Amini           errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
117019f176b9SMehdi Amini           report_fatal_error("ThinLTO: Can't get an output file for the "
117119f176b9SMehdi Amini                              "remarks");
117219f176b9SMehdi Amini         }
1173f95f77adSMehdi Amini 
11747c4a1a8dSMehdi Amini         // Parse module now
117505a358cdSSteven Wu         auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1176a61f5e37STeresa Johnson                                              /*IsImporting*/ false);
11777c4a1a8dSMehdi Amini 
11787c4a1a8dSMehdi Amini         // Save temps: original file.
11797c4a1a8dSMehdi Amini         saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
11807c4a1a8dSMehdi Amini 
11811aafabf7SMehdi Amini         auto &ImportList = ImportLists[ModuleIdentifier];
1182059464feSMehdi Amini         // Run the main process now, and generates a binary
1183f95f77adSMehdi Amini         auto OutputBuffer = ProcessThinLTOModule(
118401e32130SMehdi Amini             *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
11854d2613f2STeresa Johnson             ExportList, GUIDPreservedSymbols,
11864d2613f2STeresa Johnson             ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
1187e978f6bcSFlorian Hahn             DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,
1188ceadf6eeSNikita Popov             DebugPassManager);
1189f95f77adSMehdi Amini 
11908e13bc45SMehdi Amini         // Commit to the cache (if enabled)
11918e13bc45SMehdi Amini         CacheEntry.write(*OutputBuffer);
11928e13bc45SMehdi Amini 
11938e13bc45SMehdi Amini         if (SavedObjectsDirectoryPath.empty()) {
11948e13bc45SMehdi Amini           // We need to generated a memory buffer for the linker.
11958e13bc45SMehdi Amini           if (!CacheEntryPath.empty()) {
11960b01dfbbSEkaterina Romanova             // When cache is enabled, reload from the cache if possible.
11970b01dfbbSEkaterina Romanova             // Releasing the buffer from the heap and reloading it from the
11980b01dfbbSEkaterina Romanova             // cache file with mmap helps us to lower memory pressure.
11990b01dfbbSEkaterina Romanova             // The freed memory can be used for the next input file.
12000b01dfbbSEkaterina Romanova             // The final binary link will read from the VFS cache (hopefully!)
12010b01dfbbSEkaterina Romanova             // or from disk (if the memory pressure was too high).
12028e13bc45SMehdi Amini             auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
12038e13bc45SMehdi Amini             if (auto EC = ReloadedBufferOrErr.getError()) {
12040b01dfbbSEkaterina Romanova               // On error, keep the preexisting buffer and print a diagnostic.
1205d7fad626Sromanova-ekaterina               errs() << "remark: can't reload cached file '" << CacheEntryPath
12068e13bc45SMehdi Amini                      << "': " << EC.message() << "\n";
12078e13bc45SMehdi Amini             } else {
12088e13bc45SMehdi Amini               OutputBuffer = std::move(*ReloadedBufferOrErr);
12098e13bc45SMehdi Amini             }
12108e13bc45SMehdi Amini           }
1211f95f77adSMehdi Amini           ProducedBinaries[count] = std::move(OutputBuffer);
12128e13bc45SMehdi Amini           return;
12138e13bc45SMehdi Amini         }
12148e13bc45SMehdi Amini         ProducedBinaryFiles[count] = writeGeneratedObject(
12156c9f6fd1SSteven Wu             count, CacheEntryPath, *OutputBuffer);
1216819e9cdfSMehdi Amini       }, IndexCount);
12177c4a1a8dSMehdi Amini     }
12187c4a1a8dSMehdi Amini   }
12197c4a1a8dSMehdi Amini 
1220cead56fbSPeter Collingbourne   pruneCache(CacheOptions.Path, CacheOptions.Policy);
1221f95f77adSMehdi Amini 
12227c4a1a8dSMehdi Amini   // If statistics were requested, print them out now.
12237c4a1a8dSMehdi Amini   if (llvm::AreStatisticsEnabled())
12247c4a1a8dSMehdi Amini     llvm::PrintStatistics();
1225852f6fdeSJames Henderson   reportAndResetTimings();
12267c4a1a8dSMehdi Amini }
1227