blob: bfb8a5c76a25570b10d7cf7f6aa9593bd991a08a [file] [log] [blame]
Teresa Johnsondf6edc52016-05-23 22:54:06 +00001//===-LTO.cpp - LLVM Link Time Optimizer ----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements functions and classes used to support LTO.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/LTO/LTO.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000015#include "llvm/Analysis/TargetLibraryInfo.h"
16#include "llvm/Analysis/TargetTransformInfo.h"
Teresa Johnsondf6edc52016-05-23 22:54:06 +000017#include "llvm/Bitcode/ReaderWriter.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000018#include "llvm/CodeGen/Analysis.h"
19#include "llvm/IR/AutoUpgrade.h"
20#include "llvm/IR/DiagnosticPrinter.h"
21#include "llvm/IR/LegacyPassManager.h"
22#include "llvm/LTO/LTOBackend.h"
23#include "llvm/Linker/IRMover.h"
24#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
25#include "llvm/Support/ManagedStatic.h"
Teresa Johnsondf6edc52016-05-23 22:54:06 +000026#include "llvm/Support/MemoryBuffer.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000027#include "llvm/Support/Path.h"
Mehdi Aminiadc0e262016-08-23 21:30:12 +000028#include "llvm/Support/SHA1.h"
Teresa Johnsondf6edc52016-05-23 22:54:06 +000029#include "llvm/Support/SourceMgr.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000030#include "llvm/Support/TargetRegistry.h"
31#include "llvm/Support/ThreadPool.h"
Teresa Johnsonec544c52016-10-19 17:35:01 +000032#include "llvm/Support/Threading.h"
Teresa Johnsondf6edc52016-05-23 22:54:06 +000033#include "llvm/Support/raw_ostream.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000034#include "llvm/Target/TargetMachine.h"
35#include "llvm/Target/TargetOptions.h"
36#include "llvm/Transforms/IPO.h"
37#include "llvm/Transforms/IPO/PassManagerBuilder.h"
38#include "llvm/Transforms/Utils/SplitModule.h"
Teresa Johnsondf6edc52016-05-23 22:54:06 +000039
Teresa Johnson9ba95f92016-08-11 14:58:12 +000040#include <set>
41
42using namespace llvm;
43using namespace lto;
44using namespace object;
Teresa Johnsondf6edc52016-05-23 22:54:06 +000045
Mehdi Aminiadc0e262016-08-23 21:30:12 +000046#define DEBUG_TYPE "lto"
47
48// Returns a unique hash for the Module considering the current list of
49// export/import and other global analysis results.
50// The hash is produced in \p Key.
51static void computeCacheKey(
52 SmallString<40> &Key, const ModuleSummaryIndex &Index, StringRef ModuleID,
53 const FunctionImporter::ImportMapTy &ImportList,
54 const FunctionImporter::ExportSetTy &ExportList,
55 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
56 const GVSummaryMapTy &DefinedGlobals) {
57 // Compute the unique hash for this entry.
58 // This is based on the current compiler version, the module itself, the
59 // export list, the hash for every single module in the import list, the
60 // list of ResolvedODR for the module, and the list of preserved symbols.
61 SHA1 Hasher;
62
63 // Start with the compiler revision
64 Hasher.update(LLVM_VERSION_STRING);
65#ifdef HAVE_LLVM_REVISION
66 Hasher.update(LLVM_REVISION);
67#endif
68
69 // Include the hash for the current module
70 auto ModHash = Index.getModuleHash(ModuleID);
71 Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash)));
72 for (auto F : ExportList)
73 // The export list can impact the internalization, be conservative here
74 Hasher.update(ArrayRef<uint8_t>((uint8_t *)&F, sizeof(F)));
75
76 // Include the hash for every module we import functions from
77 for (auto &Entry : ImportList) {
78 auto ModHash = Index.getModuleHash(Entry.first());
79 Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash)));
80 }
81
82 // Include the hash for the resolved ODR.
83 for (auto &Entry : ResolvedODR) {
84 Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&Entry.first,
85 sizeof(GlobalValue::GUID)));
86 Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&Entry.second,
87 sizeof(GlobalValue::LinkageTypes)));
88 }
89
90 // Include the hash for the linkage type to reflect internalization and weak
91 // resolution.
92 for (auto &GS : DefinedGlobals) {
93 GlobalValue::LinkageTypes Linkage = GS.second->linkage();
94 Hasher.update(
95 ArrayRef<uint8_t>((const uint8_t *)&Linkage, sizeof(Linkage)));
96 }
97
98 Key = toHex(Hasher.result());
99}
100
Teresa Johnsondf6edc52016-05-23 22:54:06 +0000101// Simple helper to load a module from bitcode
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000102std::unique_ptr<Module>
103llvm::loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
104 bool Lazy) {
Teresa Johnsondf6edc52016-05-23 22:54:06 +0000105 SMDiagnostic Err;
106 ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
107 if (Lazy) {
108 ModuleOrErr =
109 getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer, false), Context,
110 /* ShouldLazyLoadMetadata */ Lazy);
111 } else {
112 ModuleOrErr = parseBitcodeFile(Buffer, Context);
113 }
114 if (std::error_code EC = ModuleOrErr.getError()) {
115 Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
116 EC.message());
117 Err.print("ThinLTO", errs());
118 report_fatal_error("Can't load module, abort.");
119 }
120 return std::move(ModuleOrErr.get());
121}
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000122
123static void thinLTOResolveWeakForLinkerGUID(
124 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
125 DenseSet<GlobalValueSummary *> &GlobalInvolvedWithAlias,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000126 function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000127 isPrevailing,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000128 function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000129 recordNewLinkage) {
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000130 for (auto &S : GVSummaryList) {
131 if (GlobalInvolvedWithAlias.count(S.get()))
132 continue;
133 GlobalValue::LinkageTypes OriginalLinkage = S->linkage();
134 if (!GlobalValue::isWeakForLinker(OriginalLinkage))
135 continue;
Peter Collingbourne73589f32016-07-07 18:31:51 +0000136 // We need to emit only one of these. The prevailing module will keep it,
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000137 // but turned into a weak, while the others will drop it when possible.
Peter Collingbourne73589f32016-07-07 18:31:51 +0000138 if (isPrevailing(GUID, S.get())) {
Teresa Johnson28c03b52016-05-26 14:16:52 +0000139 if (GlobalValue::isLinkOnceLinkage(OriginalLinkage))
140 S->setLinkage(GlobalValue::getWeakLinkage(
141 GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000142 }
143 // Alias can't be turned into available_externally.
144 else if (!isa<AliasSummary>(S.get()) &&
145 (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) ||
146 GlobalValue::isWeakODRLinkage(OriginalLinkage)))
147 S->setLinkage(GlobalValue::AvailableExternallyLinkage);
148 if (S->linkage() != OriginalLinkage)
149 recordNewLinkage(S->modulePath(), GUID, S->linkage());
150 }
151}
152
153// Resolve Weak and LinkOnce values in the \p Index.
154//
155// We'd like to drop these functions if they are no longer referenced in the
156// current module. However there is a chance that another module is still
157// referencing them because of the import. We make sure we always emit at least
158// one copy.
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000159void llvm::thinLTOResolveWeakForLinkerInIndex(
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000160 ModuleSummaryIndex &Index,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000161 function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000162 isPrevailing,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000163 function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000164 recordNewLinkage) {
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000165 // We won't optimize the globals that are referenced by an alias for now
166 // Ideally we should turn the alias into a global and duplicate the definition
167 // when needed.
168 DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
169 for (auto &I : Index)
170 for (auto &S : I.second)
171 if (auto AS = dyn_cast<AliasSummary>(S.get()))
172 GlobalInvolvedWithAlias.insert(&AS->getAliasee());
173
174 for (auto &I : Index)
175 thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
Peter Collingbourne73589f32016-07-07 18:31:51 +0000176 isPrevailing, recordNewLinkage);
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000177}
178
179static void thinLTOInternalizeAndPromoteGUID(
180 GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000181 function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000182 for (auto &S : GVSummaryList) {
183 if (isExported(S->modulePath(), GUID)) {
184 if (GlobalValue::isLocalLinkage(S->linkage()))
185 S->setLinkage(GlobalValue::ExternalLinkage);
186 } else if (!GlobalValue::isLocalLinkage(S->linkage()))
187 S->setLinkage(GlobalValue::InternalLinkage);
188 }
189}
190
191// Update the linkages in the given \p Index to mark exported values
192// as external and non-exported values as internal.
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000193void llvm::thinLTOInternalizeAndPromoteInIndex(
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000194 ModuleSummaryIndex &Index,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000195 function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
Teresa Johnson04c9a2d2016-05-25 14:03:11 +0000196 for (auto &I : Index)
197 thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
198}
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000199
200Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
201 std::unique_ptr<InputFile> File(new InputFile);
202 std::string Msg;
203 auto DiagHandler = [](const DiagnosticInfo &DI, void *MsgP) {
204 auto *Msg = reinterpret_cast<std::string *>(MsgP);
205 raw_string_ostream OS(*Msg);
206 DiagnosticPrinterRawOStream DP(OS);
207 DI.print(DP);
208 };
209 File->Ctx.setDiagnosticHandler(DiagHandler, static_cast<void *>(&Msg));
210
211 ErrorOr<std::unique_ptr<object::IRObjectFile>> IRObj =
212 IRObjectFile::create(Object, File->Ctx);
213 if (!Msg.empty())
214 return make_error<StringError>(Msg, inconvertibleErrorCode());
215 if (!IRObj)
216 return errorCodeToError(IRObj.getError());
217 File->Obj = std::move(*IRObj);
218
219 File->Ctx.setDiagnosticHandler(nullptr, nullptr);
220
Rafael Espindola79121102016-10-25 12:02:03 +0000221 for (const auto &C : File->Obj->getModule().getComdatSymbolTable()) {
222 auto P =
223 File->ComdatMap.insert(std::make_pair(&C.second, File->Comdats.size()));
224 assert(P.second);
Rafael Espindola20aa1772016-10-25 12:28:26 +0000225 (void)P;
Rafael Espindola79121102016-10-25 12:02:03 +0000226 File->Comdats.push_back(C.first());
227 }
228
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000229 return std::move(File);
230}
231
Rafael Espindola79121102016-10-25 12:02:03 +0000232Expected<int> InputFile::Symbol::getComdatIndex() const {
233 if (!GV)
234 return -1;
235 const GlobalObject *GO;
236 if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
237 GO = GA->getBaseObject();
238 if (!GO)
239 return make_error<StringError>("Unable to determine comdat of alias!",
240 inconvertibleErrorCode());
241 } else {
242 GO = cast<GlobalObject>(GV);
243 }
244 if (const Comdat *C = GO->getComdat()) {
245 auto I = File->ComdatMap.find(C);
246 assert(I != File->ComdatMap.end());
247 return I->second;
248 }
249 return -1;
250}
251
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000252LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
253 Config &Conf)
254 : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
Mehdi Aminie7494532016-08-23 18:39:12 +0000255 Ctx(Conf) {}
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000256
257LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
258 if (!Backend)
Teresa Johnsonec544c52016-10-19 17:35:01 +0000259 this->Backend =
260 createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000261}
262
263LTO::LTO(Config Conf, ThinBackend Backend,
264 unsigned ParallelCodeGenParallelismLevel)
265 : Conf(std::move(Conf)),
266 RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
Mehdi Amini026ddbb2016-08-19 05:56:37 +0000267 ThinLTO(std::move(Backend)) {}
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000268
269// Add the given symbol to the GlobalResolutions map, and resolve its partition.
270void LTO::addSymbolToGlobalRes(IRObjectFile *Obj,
271 SmallPtrSet<GlobalValue *, 8> &Used,
272 const InputFile::Symbol &Sym,
Teresa Johnsonfaa75062016-08-11 20:38:39 +0000273 SymbolResolution Res, unsigned Partition) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000274 GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
275
276 auto &GlobalRes = GlobalResolutions[Sym.getName()];
277 if (GV) {
278 GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
279 if (Res.Prevailing)
280 GlobalRes.IRName = GV->getName();
281 }
282 if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
283 (GlobalRes.Partition != GlobalResolution::Unknown &&
284 GlobalRes.Partition != Partition))
285 GlobalRes.Partition = GlobalResolution::External;
286 else
287 GlobalRes.Partition = Partition;
288}
289
Rafael Espindola7775c332016-08-26 20:19:35 +0000290static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
291 ArrayRef<SymbolResolution> Res) {
292 StringRef Path = Input->getMemoryBufferRef().getBufferIdentifier();
293 OS << Path << '\n';
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000294 auto ResI = Res.begin();
295 for (const InputFile::Symbol &Sym : Input->symbols()) {
296 assert(ResI != Res.end());
297 SymbolResolution Res = *ResI++;
298
Rafael Espindola7775c332016-08-26 20:19:35 +0000299 OS << "-r=" << Path << ',' << Sym.getName() << ',';
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000300 if (Res.Prevailing)
Rafael Espindola7775c332016-08-26 20:19:35 +0000301 OS << 'p';
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000302 if (Res.FinalDefinitionInLinkageUnit)
Rafael Espindola7775c332016-08-26 20:19:35 +0000303 OS << 'l';
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000304 if (Res.VisibleToRegularObj)
Rafael Espindola7775c332016-08-26 20:19:35 +0000305 OS << 'x';
306 OS << '\n';
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000307 }
308 assert(ResI == Res.end());
309}
310
311Error LTO::add(std::unique_ptr<InputFile> Input,
312 ArrayRef<SymbolResolution> Res) {
313 assert(!CalledGetMaxTasks);
314
315 if (Conf.ResolutionFile)
Rafael Espindola7775c332016-08-26 20:19:35 +0000316 writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000317
Mehdi Amini9989f802016-08-19 15:35:44 +0000318 // FIXME: move to backend
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000319 Module &M = Input->Obj->getModule();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000320 if (!Conf.OverrideTriple.empty())
321 M.setTargetTriple(Conf.OverrideTriple);
322 else if (M.getTargetTriple().empty())
323 M.setTargetTriple(Conf.DefaultTriple);
324
325 MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
326 bool HasThinLTOSummary = hasGlobalValueSummary(MBRef, Conf.DiagHandler);
327
328 if (HasThinLTOSummary)
329 return addThinLTO(std::move(Input), Res);
330 else
331 return addRegularLTO(std::move(Input), Res);
332}
333
334// Add a regular LTO object to the link.
335Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
336 ArrayRef<SymbolResolution> Res) {
Mehdi Aminie7494532016-08-23 18:39:12 +0000337 if (!RegularLTO.CombinedModule) {
338 RegularLTO.CombinedModule =
339 llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
340 RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
341 }
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000342 ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
343 IRObjectFile::create(Input->Obj->getMemoryBufferRef(), RegularLTO.Ctx);
344 if (!ObjOrErr)
345 return errorCodeToError(ObjOrErr.getError());
346 std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
347
348 Module &M = Obj->getModule();
349 M.materializeMetadata();
350 UpgradeDebugInfo(M);
351
352 SmallPtrSet<GlobalValue *, 8> Used;
353 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
354
355 std::vector<GlobalValue *> Keep;
356
357 for (GlobalVariable &GV : M.globals())
358 if (GV.hasAppendingLinkage())
359 Keep.push_back(&GV);
360
361 auto ResI = Res.begin();
362 for (const InputFile::Symbol &Sym :
Rafael Espindola79121102016-10-25 12:02:03 +0000363 make_range(InputFile::symbol_iterator(Obj->symbol_begin(), nullptr),
364 InputFile::symbol_iterator(Obj->symbol_end(), nullptr))) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000365 assert(ResI != Res.end());
366 SymbolResolution Res = *ResI++;
367 addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
368
369 GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
Davide Italiano39ccd242016-09-13 18:45:13 +0000370 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)
371 continue;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000372 if (Res.Prevailing && GV) {
373 Keep.push_back(GV);
374 switch (GV->getLinkage()) {
375 default:
376 break;
377 case GlobalValue::LinkOnceAnyLinkage:
378 GV->setLinkage(GlobalValue::WeakAnyLinkage);
379 break;
380 case GlobalValue::LinkOnceODRLinkage:
381 GV->setLinkage(GlobalValue::WeakODRLinkage);
382 break;
383 }
384 }
Mehdi Aminib2f46d1d2016-09-14 21:05:04 +0000385 // Common resolution: collect the maximum size/alignment over all commons.
386 // We also record if we see an instance of a common as prevailing, so that
387 // if none is prevailing we can ignore it later.
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000388 if (Sym.getFlags() & object::BasicSymbolRef::SF_Common) {
389 auto &CommonRes = RegularLTO.Commons[Sym.getIRName()];
390 CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
391 CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
Mehdi Aminib2f46d1d2016-09-14 21:05:04 +0000392 CommonRes.Prevailing |= Res.Prevailing;
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000393 }
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000394
395 // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
396 }
397 assert(ResI == Res.end());
398
Mehdi Aminie7494532016-08-23 18:39:12 +0000399 return RegularLTO.Mover->move(Obj->takeModule(), Keep,
Teresa Johnson4b9b3792016-10-12 18:39:29 +0000400 [](GlobalValue &, IRMover::ValueAdder) {},
401 /* LinkModuleInlineAsm */ true);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000402}
403
404// Add a ThinLTO object to the link.
405Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
406 ArrayRef<SymbolResolution> Res) {
407 Module &M = Input->Obj->getModule();
408 SmallPtrSet<GlobalValue *, 8> Used;
409 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
410
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000411 MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
412 ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
413 SummaryObjOrErr =
414 object::ModuleSummaryIndexObjectFile::create(MBRef, Conf.DiagHandler);
415 if (!SummaryObjOrErr)
416 return errorCodeToError(SummaryObjOrErr.getError());
417 ThinLTO.CombinedIndex.mergeFrom((*SummaryObjOrErr)->takeIndex(),
418 ThinLTO.ModuleMap.size());
419
420 auto ResI = Res.begin();
421 for (const InputFile::Symbol &Sym : Input->symbols()) {
422 assert(ResI != Res.end());
423 SymbolResolution Res = *ResI++;
424 addSymbolToGlobalRes(Input->Obj.get(), Used, Sym, Res,
425 ThinLTO.ModuleMap.size() + 1);
426
427 GlobalValue *GV = Input->Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
428 if (Res.Prevailing && GV)
429 ThinLTO.PrevailingModuleForGUID[GV->getGUID()] =
430 MBRef.getBufferIdentifier();
431 }
432 assert(ResI == Res.end());
433
434 ThinLTO.ModuleMap[MBRef.getBufferIdentifier()] = MBRef;
435 return Error();
436}
437
Teresa Johnsonfaa75062016-08-11 20:38:39 +0000438unsigned LTO::getMaxTasks() const {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000439 CalledGetMaxTasks = true;
440 return RegularLTO.ParallelCodeGenParallelismLevel + ThinLTO.ModuleMap.size();
441}
442
Peter Collingbourne80186a52016-09-23 21:33:43 +0000443Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
Teresa Johnson8dd61ae2016-09-16 13:54:19 +0000444 // Save the status of having a regularLTO combined module, as
445 // this is needed for generating the ThinLTO Task ID, and
446 // the CombinedModule will be moved at the end of runRegularLTO.
447 bool HasRegularLTO = RegularLTO.CombinedModule != nullptr;
Mehdi Aminie7494532016-08-23 18:39:12 +0000448 // Invoke regular LTO if there was a regular LTO module to start with.
Teresa Johnson8dd61ae2016-09-16 13:54:19 +0000449 if (HasRegularLTO)
Peter Collingbourne80186a52016-09-23 21:33:43 +0000450 if (auto E = runRegularLTO(AddStream))
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000451 return E;
Peter Collingbourne80186a52016-09-23 21:33:43 +0000452 return runThinLTO(AddStream, Cache, HasRegularLTO);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000453}
454
Peter Collingbourne80186a52016-09-23 21:33:43 +0000455Error LTO::runRegularLTO(AddStreamFn AddStream) {
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000456 // Make sure commons have the right size/alignment: we kept the largest from
457 // all the prevailing when adding the inputs, and we apply it here.
Teresa Johnsone2e621a2016-08-27 04:41:22 +0000458 const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000459 for (auto &I : RegularLTO.Commons) {
Mehdi Aminib2f46d1d2016-09-14 21:05:04 +0000460 if (!I.second.Prevailing)
461 // Don't do anything if no instance of this common was prevailing.
462 continue;
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000463 GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first);
Teresa Johnsone2e621a2016-08-27 04:41:22 +0000464 if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) {
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000465 // Don't create a new global if the type is already correct, just make
466 // sure the alignment is correct.
467 OldGV->setAlignment(I.second.Align);
468 continue;
469 }
Teresa Johnsone2e621a2016-08-27 04:41:22 +0000470 ArrayType *Ty =
471 ArrayType::get(Type::getInt8Ty(RegularLTO.Ctx), I.second.Size);
Mehdi Aminidc4c8cf2016-08-22 06:25:46 +0000472 auto *GV = new GlobalVariable(*RegularLTO.CombinedModule, Ty, false,
473 GlobalValue::CommonLinkage,
474 ConstantAggregateZero::get(Ty), "");
475 GV->setAlignment(I.second.Align);
476 if (OldGV) {
477 OldGV->replaceAllUsesWith(ConstantExpr::getBitCast(GV, OldGV->getType()));
478 GV->takeName(OldGV);
479 OldGV->eraseFromParent();
480 } else {
481 GV->setName(I.first);
482 }
483 }
484
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000485 if (Conf.PreOptModuleHook &&
486 !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
487 return Error();
488
Mehdi Aminid310b472016-08-22 06:25:41 +0000489 if (!Conf.CodeGenOnly) {
490 for (const auto &R : GlobalResolutions) {
491 if (R.second.IRName.empty())
492 continue;
493 if (R.second.Partition != 0 &&
494 R.second.Partition != GlobalResolution::External)
495 continue;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000496
Mehdi Aminid310b472016-08-22 06:25:41 +0000497 GlobalValue *GV =
498 RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
499 // Ignore symbols defined in other partitions.
500 if (!GV || GV->hasLocalLinkage())
501 continue;
502 GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
503 : GlobalValue::UnnamedAddr::None);
504 if (R.second.Partition == 0)
505 GV->setLinkage(GlobalValue::InternalLinkage);
506 }
507
508 if (Conf.PostInternalizeModuleHook &&
509 !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
510 return Error();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000511 }
Peter Collingbourne80186a52016-09-23 21:33:43 +0000512 return backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000513 std::move(RegularLTO.CombinedModule));
514}
515
516/// This class defines the interface to the ThinLTO backend.
517class lto::ThinBackendProc {
518protected:
519 Config &Conf;
520 ModuleSummaryIndex &CombinedIndex;
Mehdi Amini767e1452016-09-06 03:23:45 +0000521 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000522
523public:
524 ThinBackendProc(Config &Conf, ModuleSummaryIndex &CombinedIndex,
Mehdi Amini767e1452016-09-06 03:23:45 +0000525 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries)
Mehdi Amini18b91112016-08-19 06:10:03 +0000526 : Conf(Conf), CombinedIndex(CombinedIndex),
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000527 ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries) {}
528
529 virtual ~ThinBackendProc() {}
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000530 virtual Error start(
531 unsigned Task, MemoryBufferRef MBRef,
532 const FunctionImporter::ImportMapTy &ImportList,
533 const FunctionImporter::ExportSetTy &ExportList,
534 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
535 MapVector<StringRef, MemoryBufferRef> &ModuleMap) = 0;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000536 virtual Error wait() = 0;
537};
538
539class InProcessThinBackend : public ThinBackendProc {
540 ThreadPool BackendThreadPool;
Peter Collingbourne80186a52016-09-23 21:33:43 +0000541 AddStreamFn AddStream;
542 NativeObjectCache Cache;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000543
544 Optional<Error> Err;
545 std::mutex ErrMu;
546
547public:
Mehdi Amini767e1452016-09-06 03:23:45 +0000548 InProcessThinBackend(
549 Config &Conf, ModuleSummaryIndex &CombinedIndex,
550 unsigned ThinLTOParallelismLevel,
551 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
Peter Collingbourne80186a52016-09-23 21:33:43 +0000552 AddStreamFn AddStream, NativeObjectCache Cache)
Mehdi Amini18b91112016-08-19 06:10:03 +0000553 : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
554 BackendThreadPool(ThinLTOParallelismLevel),
Peter Collingbourne80186a52016-09-23 21:33:43 +0000555 AddStream(std::move(AddStream)), Cache(std::move(Cache)) {}
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000556
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000557 Error runThinLTOBackendThread(
Peter Collingbourne80186a52016-09-23 21:33:43 +0000558 AddStreamFn AddStream, NativeObjectCache Cache, unsigned Task,
559 MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000560 const FunctionImporter::ImportMapTy &ImportList,
561 const FunctionImporter::ExportSetTy &ExportList,
562 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
563 const GVSummaryMapTy &DefinedGlobals,
564 MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
Peter Collingbourne80186a52016-09-23 21:33:43 +0000565 auto RunThinBackend = [&](AddStreamFn AddStream) {
566 LTOLLVMContext BackendContext(Conf);
567 ErrorOr<std::unique_ptr<Module>> MOrErr =
568 parseBitcodeFile(MBRef, BackendContext);
569 assert(MOrErr && "Unable to load module in thread?");
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000570
Peter Collingbourne80186a52016-09-23 21:33:43 +0000571 return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
572 ImportList, DefinedGlobals, ModuleMap);
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000573 };
Peter Collingbourne80186a52016-09-23 21:33:43 +0000574
Mehdi Amini00fa1402016-10-08 04:44:18 +0000575 auto ModuleID = MBRef.getBufferIdentifier();
Mehdi Aminif82bda02016-10-08 04:44:23 +0000576
577 if (!Cache || !CombinedIndex.modulePaths().count(ModuleID) ||
578 all_of(CombinedIndex.getModuleHash(ModuleID),
579 [](uint32_t V) { return V == 0; }))
580 // Cache disabled or no entry for this module in the combined index or
581 // no module hash.
Peter Collingbourne80186a52016-09-23 21:33:43 +0000582 return RunThinBackend(AddStream);
583
584 SmallString<40> Key;
585 // The module may be cached, this helps handling it.
Mehdi Amini00fa1402016-10-08 04:44:18 +0000586 computeCacheKey(Key, CombinedIndex, ModuleID, ImportList, ExportList,
587 ResolvedODR, DefinedGlobals);
Peter Collingbourne80186a52016-09-23 21:33:43 +0000588 if (AddStreamFn CacheAddStream = Cache(Task, Key))
589 return RunThinBackend(CacheAddStream);
590
591 return Error();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000592 }
593
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000594 Error start(
595 unsigned Task, MemoryBufferRef MBRef,
596 const FunctionImporter::ImportMapTy &ImportList,
597 const FunctionImporter::ExportSetTy &ExportList,
598 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
599 MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000600 StringRef ModulePath = MBRef.getBufferIdentifier();
Mehdi Amini767e1452016-09-06 03:23:45 +0000601 assert(ModuleToDefinedGVSummaries.count(ModulePath));
602 const GVSummaryMapTy &DefinedGlobals =
603 ModuleToDefinedGVSummaries.find(ModulePath)->second;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000604 BackendThreadPool.async(
605 [=](MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
606 const FunctionImporter::ImportMapTy &ImportList,
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000607 const FunctionImporter::ExportSetTy &ExportList,
608 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
609 &ResolvedODR,
Mehdi Amini767e1452016-09-06 03:23:45 +0000610 const GVSummaryMapTy &DefinedGlobals,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000611 MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000612 Error E = runThinLTOBackendThread(
Peter Collingbourne80186a52016-09-23 21:33:43 +0000613 AddStream, Cache, Task, MBRef, CombinedIndex, ImportList,
614 ExportList, ResolvedODR, DefinedGlobals, ModuleMap);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000615 if (E) {
616 std::unique_lock<std::mutex> L(ErrMu);
617 if (Err)
618 Err = joinErrors(std::move(*Err), std::move(E));
619 else
620 Err = std::move(E);
621 }
622 },
Mehdi Aminicdbcbf72016-08-16 05:46:05 +0000623 MBRef, std::ref(CombinedIndex), std::ref(ImportList),
Mehdi Amini767e1452016-09-06 03:23:45 +0000624 std::ref(ExportList), std::ref(ResolvedODR), std::ref(DefinedGlobals),
625 std::ref(ModuleMap));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000626 return Error();
627 }
628
629 Error wait() override {
630 BackendThreadPool.wait();
631 if (Err)
632 return std::move(*Err);
633 else
634 return Error();
635 }
636};
637
638ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) {
639 return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
Mehdi Amini767e1452016-09-06 03:23:45 +0000640 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
Peter Collingbourne80186a52016-09-23 21:33:43 +0000641 AddStreamFn AddStream, NativeObjectCache Cache) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000642 return llvm::make_unique<InProcessThinBackend>(
643 Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
Peter Collingbourne80186a52016-09-23 21:33:43 +0000644 AddStream, Cache);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000645 };
646}
647
Teresa Johnson3f212b82016-09-21 19:12:05 +0000648// Given the original \p Path to an output file, replace any path
649// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
650// resulting directory if it does not yet exist.
651std::string lto::getThinLTOOutputFile(const std::string &Path,
652 const std::string &OldPrefix,
653 const std::string &NewPrefix) {
654 if (OldPrefix.empty() && NewPrefix.empty())
655 return Path;
656 SmallString<128> NewPath(Path);
657 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
658 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
659 if (!ParentPath.empty()) {
660 // Make sure the new directory exists, creating it if necessary.
661 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
662 llvm::errs() << "warning: could not create directory '" << ParentPath
663 << "': " << EC.message() << '\n';
664 }
665 return NewPath.str();
666}
667
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000668class WriteIndexesThinBackend : public ThinBackendProc {
669 std::string OldPrefix, NewPrefix;
670 bool ShouldEmitImportsFiles;
671
672 std::string LinkedObjectsFileName;
673 std::unique_ptr<llvm::raw_fd_ostream> LinkedObjectsFile;
674
675public:
Mehdi Amini767e1452016-09-06 03:23:45 +0000676 WriteIndexesThinBackend(
677 Config &Conf, ModuleSummaryIndex &CombinedIndex,
678 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
679 std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles,
680 std::string LinkedObjectsFileName)
Mehdi Amini18b91112016-08-19 06:10:03 +0000681 : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000682 OldPrefix(OldPrefix), NewPrefix(NewPrefix),
683 ShouldEmitImportsFiles(ShouldEmitImportsFiles),
684 LinkedObjectsFileName(LinkedObjectsFileName) {}
685
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000686 Error start(
687 unsigned Task, MemoryBufferRef MBRef,
688 const FunctionImporter::ImportMapTy &ImportList,
689 const FunctionImporter::ExportSetTy &ExportList,
690 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
691 MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000692 StringRef ModulePath = MBRef.getBufferIdentifier();
693 std::string NewModulePath =
694 getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
695
696 std::error_code EC;
697 if (!LinkedObjectsFileName.empty()) {
698 if (!LinkedObjectsFile) {
699 LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>(
700 LinkedObjectsFileName, EC, sys::fs::OpenFlags::F_None);
701 if (EC)
702 return errorCodeToError(EC);
703 }
704 *LinkedObjectsFile << NewModulePath << '\n';
705 }
706
707 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
708 gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
Mehdi Aminicdbcbf72016-08-16 05:46:05 +0000709 ImportList, ModuleToSummariesForIndex);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000710
711 raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
712 sys::fs::OpenFlags::F_None);
713 if (EC)
714 return errorCodeToError(EC);
715 WriteIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex);
716
717 if (ShouldEmitImportsFiles)
Mehdi Aminicdbcbf72016-08-16 05:46:05 +0000718 return errorCodeToError(
719 EmitImportsFiles(ModulePath, NewModulePath + ".imports", ImportList));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000720 return Error();
721 }
722
723 Error wait() override { return Error(); }
724};
725
726ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
727 std::string NewPrefix,
728 bool ShouldEmitImportsFiles,
729 std::string LinkedObjectsFile) {
730 return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
Mehdi Amini767e1452016-09-06 03:23:45 +0000731 const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
Peter Collingbourne80186a52016-09-23 21:33:43 +0000732 AddStreamFn AddStream, NativeObjectCache Cache) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000733 return llvm::make_unique<WriteIndexesThinBackend>(
Mehdi Amini18b91112016-08-19 06:10:03 +0000734 Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix, NewPrefix,
735 ShouldEmitImportsFiles, LinkedObjectsFile);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000736 };
737}
738
Peter Collingbourne80186a52016-09-23 21:33:43 +0000739Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
740 bool HasRegularLTO) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000741 if (ThinLTO.ModuleMap.empty())
742 return Error();
743
744 if (Conf.CombinedIndexHook && !Conf.CombinedIndexHook(ThinLTO.CombinedIndex))
745 return Error();
746
747 // Collect for each module the list of function it defines (GUID ->
748 // Summary).
749 StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
750 ModuleToDefinedGVSummaries(ThinLTO.ModuleMap.size());
751 ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
752 ModuleToDefinedGVSummaries);
Teresa Johnson620c1402016-09-20 23:07:17 +0000753 // Create entries for any modules that didn't have any GV summaries
754 // (either they didn't have any GVs to start with, or we suppressed
755 // generation of the summaries because they e.g. had inline assembly
756 // uses that couldn't be promoted/renamed on export). This is so
757 // InProcessThinBackend::start can still launch a backend thread, which
758 // is passed the map of summaries for the module, without any special
759 // handling for this case.
760 for (auto &Mod : ThinLTO.ModuleMap)
761 if (!ModuleToDefinedGVSummaries.count(Mod.first))
762 ModuleToDefinedGVSummaries.try_emplace(Mod.first);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000763
764 StringMap<FunctionImporter::ImportMapTy> ImportLists(
765 ThinLTO.ModuleMap.size());
766 StringMap<FunctionImporter::ExportSetTy> ExportLists(
767 ThinLTO.ModuleMap.size());
768 ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
769 ImportLists, ExportLists);
770
771 std::set<GlobalValue::GUID> ExportedGUIDs;
772 for (auto &Res : GlobalResolutions) {
773 if (!Res.second.IRName.empty() &&
774 Res.second.Partition == GlobalResolution::External)
775 ExportedGUIDs.insert(GlobalValue::getGUID(Res.second.IRName));
776 }
777
778 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
779 return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
780 };
781 auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
782 const auto &ExportList = ExportLists.find(ModuleIdentifier);
783 return (ExportList != ExportLists.end() &&
784 ExportList->second.count(GUID)) ||
785 ExportedGUIDs.count(GUID);
786 };
787 thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000788
789 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
790 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
791 GlobalValue::GUID GUID,
792 GlobalValue::LinkageTypes NewLinkage) {
793 ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
794 };
795
796 thinLTOResolveWeakForLinkerInIndex(ThinLTO.CombinedIndex, isPrevailing,
797 recordNewLinkage);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000798
Peter Collingbourne80186a52016-09-23 21:33:43 +0000799 std::unique_ptr<ThinBackendProc> BackendProc =
800 ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
801 AddStream, Cache);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000802
803 // Partition numbers for ThinLTO jobs start at 1 (see comments for
804 // GlobalResolution in LTO.h). Task numbers, however, start at
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000805 // ParallelCodeGenParallelismLevel if an LTO module is present, as tasks 0
806 // through ParallelCodeGenParallelismLevel-1 are reserved for parallel code
807 // generation partitions.
Teresa Johnson8dd61ae2016-09-16 13:54:19 +0000808 unsigned Task =
809 HasRegularLTO ? RegularLTO.ParallelCodeGenParallelismLevel : 0;
Teresa Johnsonfaa75062016-08-11 20:38:39 +0000810 unsigned Partition = 1;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000811
812 for (auto &Mod : ThinLTO.ModuleMap) {
Mehdi Aminicdbcbf72016-08-16 05:46:05 +0000813 if (Error E = BackendProc->start(Task, Mod.second, ImportLists[Mod.first],
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000814 ExportLists[Mod.first],
815 ResolvedODR[Mod.first], ThinLTO.ModuleMap))
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000816 return E;
817
818 ++Task;
819 ++Partition;
820 }
821
822 return BackendProc->wait();
Teresa Johnsondf6edc52016-05-23 22:54:06 +0000823}