blob: ee2197994587d533acfba68d8bf48e89c8459943 [file] [log] [blame]
Mehdi Amini7c4a1a82016-03-09 01:37:22 +00001//===-ThinLTOCodeGenerator.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 the Thin Link Time Optimization library. This library is
11// intended to be used by linker to optimize code at link time.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/LTO/ThinLTOCodeGenerator.h"
16
Teresa Johnsoncec0cae2016-03-14 21:18:10 +000017#include "llvm/ADT/Statistic.h"
Teresa Johnson26ab5772016-03-15 00:04:37 +000018#include "llvm/ADT/StringExtras.h"
Teresa Johnson2d5487c2016-04-11 13:58:45 +000019#include "llvm/Analysis/ModuleSummaryAnalysis.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000020#include "llvm/Analysis/TargetLibraryInfo.h"
21#include "llvm/Analysis/TargetTransformInfo.h"
Teresa Johnsoncec0cae2016-03-14 21:18:10 +000022#include "llvm/Bitcode/BitcodeWriterPass.h"
Teresa Johnson26ab5772016-03-15 00:04:37 +000023#include "llvm/Bitcode/ReaderWriter.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000024#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
Teresa Johnsoncec0cae2016-03-14 21:18:10 +000025#include "llvm/IR/DiagnosticPrinter.h"
Teresa Johnson26ab5772016-03-15 00:04:37 +000026#include "llvm/IR/LLVMContext.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000027#include "llvm/IR/LegacyPassManager.h"
28#include "llvm/IR/Mangler.h"
29#include "llvm/IRReader/IRReader.h"
30#include "llvm/Linker/Linker.h"
31#include "llvm/MC/SubtargetFeature.h"
Teresa Johnson26ab5772016-03-15 00:04:37 +000032#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
Mehdi Amini1aafabf2016-04-16 07:02:16 +000033#include "llvm/Support/Debug.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000034#include "llvm/Support/SourceMgr.h"
35#include "llvm/Support/TargetRegistry.h"
36#include "llvm/Support/ThreadPool.h"
37#include "llvm/Target/TargetMachine.h"
38#include "llvm/Transforms/IPO.h"
39#include "llvm/Transforms/IPO/FunctionImport.h"
40#include "llvm/Transforms/IPO/PassManagerBuilder.h"
41#include "llvm/Transforms/ObjCARC.h"
42#include "llvm/Transforms/Utils/FunctionImportUtils.h"
43
44using namespace llvm;
45
Mehdi Amini1aafabf2016-04-16 07:02:16 +000046#define DEBUG_TYPE "thinlto"
47
Mehdi Amini09b4a8d2016-03-10 01:28:54 +000048namespace llvm {
49// Flags -discard-value-names, defined in LTOCodeGenerator.cpp
50extern cl::opt<bool> LTODiscardValueNames;
51}
52
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000053namespace {
54
55static cl::opt<int> ThreadCount("threads",
56 cl::init(std::thread::hardware_concurrency()));
57
58static void diagnosticHandler(const DiagnosticInfo &DI) {
59 DiagnosticPrinterRawOStream DP(errs());
60 DI.print(DP);
61 errs() << '\n';
62}
63
64// Simple helper to load a module from bitcode
65static std::unique_ptr<Module>
66loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
67 bool Lazy) {
68 SMDiagnostic Err;
69 ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
70 if (Lazy) {
71 ModuleOrErr =
72 getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer, false), Context,
73 /* ShouldLazyLoadMetadata */ Lazy);
74 } else {
75 ModuleOrErr = parseBitcodeFile(Buffer, Context);
76 }
77 if (std::error_code EC = ModuleOrErr.getError()) {
78 Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
79 EC.message());
80 Err.print("ThinLTO", errs());
81 report_fatal_error("Can't load module, abort.");
82 }
83 return std::move(ModuleOrErr.get());
84}
85
86// Simple helper to save temporary files for debug.
87static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
88 unsigned count, StringRef Suffix) {
89 if (TempDir.empty())
90 return;
91 // User asked to save temps, let dump the bitcode file after import.
92 auto SaveTempPath = TempDir + llvm::utostr(count) + Suffix;
93 std::error_code EC;
94 raw_fd_ostream OS(SaveTempPath.str(), EC, sys::fs::F_None);
95 if (EC)
96 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
97 " to save optimized bitcode\n");
Teresa Johnson3c35e092016-04-04 21:19:31 +000098 WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000099}
100
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000101bool IsFirstDefinitionForLinker(const GlobalValueInfoList &GVInfo,
102 const ModuleSummaryIndex &Index,
103 StringRef ModulePath) {
104 // Get the first *linker visible* definition for this global in the summary
105 // list.
106 auto FirstDefForLinker = llvm::find_if(
107 GVInfo, [](const std::unique_ptr<GlobalValueInfo> &FuncInfo) {
108 auto Linkage = FuncInfo->summary()->linkage();
109 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
110 });
111 // If \p GV is not the first definition, give up...
112 if ((*FirstDefForLinker)->summary()->modulePath() != ModulePath)
113 return false;
114 // If there is any strong definition anywhere, do not bother emitting this.
115 if (llvm::any_of(
116 GVInfo, [](const std::unique_ptr<GlobalValueInfo> &FuncInfo) {
117 auto Linkage = FuncInfo->summary()->linkage();
118 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
119 !GlobalValue::isWeakForLinker(Linkage);
120 }))
121 return false;
122 return true;
Hans Wennborgfa6e4142016-04-02 01:03:41 +0000123}
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000124
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000125static GlobalValue::LinkageTypes
126ResolveODR(const ModuleSummaryIndex &Index,
127 const FunctionImporter::ExportSetTy &ExportList,
128 StringRef ModuleIdentifier, GlobalValue::GUID GUID,
129 const GlobalValueSummary &GV) {
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000130 auto HasMultipleCopies =
131 [&](const GlobalValueInfoList &GVInfo) { return GVInfo.size() > 1; };
132
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000133 auto OriginalLinkage = GV.linkage();
134 switch (OriginalLinkage) {
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000135 case GlobalValue::ExternalLinkage:
136 case GlobalValue::AvailableExternallyLinkage:
137 case GlobalValue::AppendingLinkage:
138 case GlobalValue::InternalLinkage:
139 case GlobalValue::PrivateLinkage:
140 case GlobalValue::ExternalWeakLinkage:
141 case GlobalValue::CommonLinkage:
142 case GlobalValue::LinkOnceAnyLinkage:
143 case GlobalValue::WeakAnyLinkage:
144 break;
145 case GlobalValue::LinkOnceODRLinkage:
146 case GlobalValue::WeakODRLinkage: {
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000147 auto &GVInfo = Index.findGlobalValueInfoList(GUID)->second;
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000148 // We need to emit only one of these, the first module will keep
149 // it, but turned into a weak while the others will drop it.
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000150 if (!HasMultipleCopies(GVInfo)) {
151 // Exported LinkonceODR needs to be promoted to not be discarded
152 if (GlobalValue::isDiscardableIfUnused(OriginalLinkage) &&
153 ExportList.count(GUID))
154 return GlobalValue::WeakODRLinkage;
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000155 break;
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000156 }
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000157 if (IsFirstDefinitionForLinker(GVInfo, Index, ModuleIdentifier))
158 return GlobalValue::WeakODRLinkage;
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000159 else if (isa<AliasSummary>(&GV))
160 // Alias can't be turned into available_externally.
161 return OriginalLinkage;
162 return GlobalValue::AvailableExternallyLinkage;
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000163 }
164 }
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000165 return OriginalLinkage;
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000166}
167
168/// Resolve LinkOnceODR and WeakODR.
169///
170/// We'd like to drop these function if they are no longer referenced in the
171/// current module. However there is a chance that another module is still
172/// referencing them because of the import. We make sure we always emit at least
173/// one copy.
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000174static void ResolveODR(
175 const ModuleSummaryIndex &Index,
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000176 const FunctionImporter::ExportSetTy &ExportList,
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000177 const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGlobals,
178 StringRef ModuleIdentifier,
179 DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR) {
Mehdi Amini8dcc8082016-04-14 08:46:22 +0000180 if (Index.modulePaths().size() == 1)
181 // Nothing to do if we don't have multiple modules
182 return;
183
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000184 // We won't optimize the globals that are referenced by an alias for now
185 // Ideally we should turn the alias into a global and duplicate the definition
186 // when needed.
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000187 DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
188 for (auto &GA : DefinedGlobals) {
189 if (auto AS = dyn_cast<AliasSummary>(GA.second))
190 GlobalInvolvedWithAlias.insert(&AS->getAliasee());
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000191 }
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000192
193 for (auto &GV : DefinedGlobals) {
194 if (GlobalInvolvedWithAlias.count(GV.second))
195 continue;
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000196 auto NewLinkage =
197 ResolveODR(Index, ExportList, ModuleIdentifier, GV.first, *GV.second);
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000198 if (NewLinkage != GV.second->linkage()) {
199 ResolvedODR[GV.first] = NewLinkage;
200 }
201 }
202}
203
204/// Fixup linkage, see ResolveODR() above.
205void fixupODR(
206 Module &TheModule,
207 const DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR) {
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000208 // Process functions and global now
209 for (auto &GV : TheModule) {
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000210 auto NewLinkage = ResolvedODR.find(GV.getGUID());
211 if (NewLinkage == ResolvedODR.end())
212 continue;
213 DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
214 << GV.getLinkage() << " to " << NewLinkage->second << "\n");
215 GV.setLinkage(NewLinkage->second);
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000216 }
217 for (auto &GV : TheModule.globals()) {
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000218 auto NewLinkage = ResolvedODR.find(GV.getGUID());
219 if (NewLinkage == ResolvedODR.end())
220 continue;
221 DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
222 << GV.getLinkage() << " to " << NewLinkage->second << "\n");
223 GV.setLinkage(NewLinkage->second);
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000224 }
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000225 for (auto &GV : TheModule.aliases()) {
226 auto NewLinkage = ResolvedODR.find(GV.getGUID());
227 if (NewLinkage == ResolvedODR.end())
228 continue;
229 DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
230 << GV.getLinkage() << " to " << NewLinkage->second << "\n");
231 GV.setLinkage(NewLinkage->second);
232 }
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000233}
234
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000235static StringMap<MemoryBufferRef>
236generateModuleMap(const std::vector<MemoryBufferRef> &Modules) {
237 StringMap<MemoryBufferRef> ModuleMap;
238 for (auto &ModuleBuffer : Modules) {
239 assert(ModuleMap.find(ModuleBuffer.getBufferIdentifier()) ==
240 ModuleMap.end() &&
241 "Expect unique Buffer Identifier");
242 ModuleMap[ModuleBuffer.getBufferIdentifier()] = ModuleBuffer;
243 }
244 return ModuleMap;
245}
246
247/// Provide a "loader" for the FunctionImporter to access function from other
248/// modules.
249class ModuleLoader {
250 /// The context that will be used for importing.
251 LLVMContext &Context;
252
253 /// Map from Module identifier to MemoryBuffer. Used by clients like the
254 /// FunctionImported to request loading a Module.
255 StringMap<MemoryBufferRef> &ModuleMap;
256
257public:
258 ModuleLoader(LLVMContext &Context, StringMap<MemoryBufferRef> &ModuleMap)
259 : Context(Context), ModuleMap(ModuleMap) {}
260
261 /// Load a module on demand.
262 std::unique_ptr<Module> operator()(StringRef Identifier) {
263 return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true);
264 }
265};
266
Teresa Johnson26ab5772016-03-15 00:04:37 +0000267static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index) {
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000268 if (renameModuleForThinLTO(TheModule, Index))
269 report_fatal_error("renameModuleForThinLTO failed");
270}
271
Mehdi Amini01e32132016-03-26 05:40:34 +0000272static void
273crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
274 StringMap<MemoryBufferRef> &ModuleMap,
275 const FunctionImporter::ImportMapTy &ImportList) {
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000276 ModuleLoader Loader(TheModule.getContext(), ModuleMap);
277 FunctionImporter Importer(Index, Loader);
Mehdi Amini01e32132016-03-26 05:40:34 +0000278 Importer.importFunctions(TheModule, ImportList);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000279}
280
281static void optimizeModule(Module &TheModule, TargetMachine &TM) {
282 // Populate the PassManager
283 PassManagerBuilder PMB;
284 PMB.LibraryInfo = new TargetLibraryInfoImpl(TM.getTargetTriple());
285 PMB.Inliner = createFunctionInliningPass();
286 // FIXME: should get it from the bitcode?
287 PMB.OptLevel = 3;
288 PMB.LoopVectorize = true;
289 PMB.SLPVectorize = true;
290 PMB.VerifyInput = true;
291 PMB.VerifyOutput = false;
292
293 legacy::PassManager PM;
294
295 // Add the TTI (required to inform the vectorizer about register size for
296 // instance)
297 PM.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
298
299 // Add optimizations
300 PMB.populateThinLTOPassManager(PM);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000301
302 PM.run(TheModule);
303}
304
305std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
306 TargetMachine &TM) {
307 SmallVector<char, 128> OutputBuffer;
308
309 // CodeGen
310 {
311 raw_svector_ostream OS(OutputBuffer);
312 legacy::PassManager PM;
Mehdi Amini215d59e2016-04-01 08:22:59 +0000313
314 // If the bitcode files contain ARC code and were compiled with optimization,
315 // the ObjCARCContractPass must be run, so do it unconditionally here.
316 PM.add(createObjCARCContractPass());
317
318 // Setup the codegen now.
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000319 if (TM.addPassesToEmitFile(PM, OS, TargetMachine::CGFT_ObjectFile,
320 /* DisableVerify */ true))
321 report_fatal_error("Failed to setup codegen");
322
323 // Run codegen now. resulting binary is in OutputBuffer.
324 PM.run(TheModule);
325 }
326 return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
327}
328
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000329static std::unique_ptr<MemoryBuffer> ProcessThinLTOModule(
330 Module &TheModule, const ModuleSummaryIndex &Index,
331 StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
332 const FunctionImporter::ImportMapTy &ImportList,
333 DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
334 ThinLTOCodeGenerator::CachingOptions CacheOptions, bool DisableCodeGen,
335 StringRef SaveTempsDir, unsigned count) {
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000336
337 // Save temps: after IPO.
338 saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc");
339
340 // "Benchmark"-like optimization: single-source case
341 bool SingleModule = (ModuleMap.size() == 1);
342
343 if (!SingleModule) {
344 promoteModule(TheModule, Index);
345
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000346 // Resolve the LinkOnce/Weak ODR, trying to turn them into
347 // "available_externally" when possible.
348 // This is a compile-time optimization.
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000349 fixupODR(TheModule, ResolvedODR);
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000350
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000351 // Save temps: after promotion.
352 saveTempBitcode(TheModule, SaveTempsDir, count, ".2.promoted.bc");
353
Mehdi Amini01e32132016-03-26 05:40:34 +0000354 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000355
356 // Save temps: after cross-module import.
357 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
358 }
359
360 optimizeModule(TheModule, TM);
361
362 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.opt.bc");
363
Mehdi Amini43b657b2016-04-01 06:47:02 +0000364 if (DisableCodeGen) {
365 // Configured to stop before CodeGen, serialize the bitcode and return.
366 SmallVector<char, 128> OutputBuffer;
367 {
368 raw_svector_ostream OS(OutputBuffer);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000369 ModuleSummaryIndexBuilder IndexBuilder(&TheModule);
370 WriteBitcodeToFile(&TheModule, OS, true, &IndexBuilder.getIndex());
Mehdi Amini43b657b2016-04-01 06:47:02 +0000371 }
372 return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
373 }
374
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000375 return codegenModule(TheModule, TM);
376}
377
378// Initialize the TargetMachine builder for a given Triple
379static void initTMBuilder(TargetMachineBuilder &TMBuilder,
380 const Triple &TheTriple) {
381 // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
382 // FIXME this looks pretty terrible...
383 if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
384 if (TheTriple.getArch() == llvm::Triple::x86_64)
385 TMBuilder.MCpu = "core2";
386 else if (TheTriple.getArch() == llvm::Triple::x86)
387 TMBuilder.MCpu = "yonah";
388 else if (TheTriple.getArch() == llvm::Triple::aarch64)
389 TMBuilder.MCpu = "cyclone";
390 }
391 TMBuilder.TheTriple = std::move(TheTriple);
392}
393
394} // end anonymous namespace
395
396void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {
397 MemoryBufferRef Buffer(Data, Identifier);
398 if (Modules.empty()) {
399 // First module added, so initialize the triple and some options
400 LLVMContext Context;
401 Triple TheTriple(getBitcodeTargetTriple(Buffer, Context));
402 initTMBuilder(TMBuilder, Triple(TheTriple));
403 }
404#ifndef NDEBUG
405 else {
406 LLVMContext Context;
407 assert(TMBuilder.TheTriple.str() ==
408 getBitcodeTargetTriple(Buffer, Context) &&
409 "ThinLTO modules with different triple not supported");
410 }
411#endif
412 Modules.push_back(Buffer);
413}
414
415void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {
416 PreservedSymbols.insert(Name);
417}
418
419void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {
420 CrossReferencedSymbols.insert(Name);
421}
422
423// TargetMachine factory
424std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
425 std::string ErrMsg;
426 const Target *TheTarget =
427 TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);
428 if (!TheTarget) {
429 report_fatal_error("Can't load target for this Triple: " + ErrMsg);
430 }
431
432 // Use MAttr as the default set of features.
433 SubtargetFeatures Features(MAttr);
434 Features.getDefaultSubtargetFeatures(TheTriple);
435 std::string FeatureStr = Features.getString();
436 return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
437 TheTriple.str(), MCpu, FeatureStr, Options, RelocModel,
438 CodeModel::Default, CGOptLevel));
439}
440
441/**
Teresa Johnson26ab5772016-03-15 00:04:37 +0000442 * Produce the combined summary index from all the bitcode files:
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000443 * "thin-link".
444 */
Teresa Johnson26ab5772016-03-15 00:04:37 +0000445std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
446 std::unique_ptr<ModuleSummaryIndex> CombinedIndex;
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000447 uint64_t NextModuleId = 0;
448 for (auto &ModuleBuffer : Modules) {
Teresa Johnson26ab5772016-03-15 00:04:37 +0000449 ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
450 object::ModuleSummaryIndexObjectFile::create(ModuleBuffer,
451 diagnosticHandler, false);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000452 if (std::error_code EC = ObjOrErr.getError()) {
453 // FIXME diagnose
Teresa Johnson26ab5772016-03-15 00:04:37 +0000454 errs() << "error: can't create ModuleSummaryIndexObjectFile for buffer: "
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000455 << EC.message() << "\n";
456 return nullptr;
457 }
458 auto Index = (*ObjOrErr)->takeIndex();
459 if (CombinedIndex) {
460 CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);
461 } else {
462 CombinedIndex = std::move(Index);
463 }
464 }
465 return CombinedIndex;
466}
467
468/**
469 * Perform promotion and renaming of exported internal functions.
470 */
471void ThinLTOCodeGenerator::promote(Module &TheModule,
Teresa Johnson26ab5772016-03-15 00:04:37 +0000472 ModuleSummaryIndex &Index) {
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000473 auto ModuleCount = Index.modulePaths().size();
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000474 auto ModuleIdentifier = TheModule.getModuleIdentifier();
475 // Collect for each module the list of function it defines (GUID -> Summary).
476 StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
477 ModuleToDefinedGVSummaries;
478 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000479
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000480 // Generate import/export list
481 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
482 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
483 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
484 ExportLists);
485 auto &ExportList = ExportLists[ModuleIdentifier];
486
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000487 // Resolve the LinkOnceODR, trying to turn them into "available_externally"
488 // where possible.
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000489 // This is a compile-time optimization.
490 DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR;
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000491 ResolveODR(Index, ExportList, ModuleToDefinedGVSummaries[ModuleIdentifier],
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000492 ModuleIdentifier, ResolvedODR);
493 fixupODR(TheModule, ResolvedODR);
Mehdi Amini5a2e5d32016-04-01 21:53:50 +0000494
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000495 promoteModule(TheModule, Index);
496}
497
498/**
499 * Perform cross-module importing for the module identified by ModuleIdentifier.
500 */
501void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
Teresa Johnson26ab5772016-03-15 00:04:37 +0000502 ModuleSummaryIndex &Index) {
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000503 auto ModuleMap = generateModuleMap(Modules);
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000504 auto ModuleCount = Index.modulePaths().size();
505
506 // Collect for each module the list of function it defines (GUID -> Summary).
507 StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
508 ModuleToDefinedGVSummaries(ModuleCount);
509 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
Mehdi Amini01e32132016-03-26 05:40:34 +0000510
511 // Generate import/export list
Mehdi Amini01e32132016-03-26 05:40:34 +0000512 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
513 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000514 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
515 ExportLists);
Mehdi Amini01e32132016-03-26 05:40:34 +0000516 auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
517
518 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000519}
520
521/**
522 * Perform post-importing ThinLTO optimizations.
523 */
524void ThinLTOCodeGenerator::optimize(Module &TheModule) {
525 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
526 optimizeModule(TheModule, *TMBuilder.create());
527}
528
529/**
530 * Perform ThinLTO CodeGen.
531 */
532std::unique_ptr<MemoryBuffer> ThinLTOCodeGenerator::codegen(Module &TheModule) {
533 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
534 return codegenModule(TheModule, *TMBuilder.create());
535}
536
537// Main entry point for the ThinLTO processing
538void ThinLTOCodeGenerator::run() {
Mehdi Amini43b657b2016-04-01 06:47:02 +0000539 if (CodeGenOnly) {
540 // Perform only parallel codegen and return.
541 ThreadPool Pool;
542 assert(ProducedBinaries.empty() && "The generator should not be reused");
543 ProducedBinaries.resize(Modules.size());
544 int count = 0;
545 for (auto &ModuleBuffer : Modules) {
546 Pool.async([&](int count) {
547 LLVMContext Context;
548 Context.setDiscardValueNames(LTODiscardValueNames);
549
550 // Parse module now
551 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
552
553 // CodeGen
554 ProducedBinaries[count] = codegen(*TheModule);
555 }, count++);
556 }
557
558 return;
559 }
560
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000561 // Sequential linking phase
562 auto Index = linkCombinedIndex();
563
564 // Save temps: index.
565 if (!SaveTempsDir.empty()) {
566 auto SaveTempPath = SaveTempsDir + "index.bc";
567 std::error_code EC;
568 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::F_None);
569 if (EC)
570 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
571 " to save optimized bitcode\n");
Teresa Johnson76a1c1d2016-03-11 18:52:24 +0000572 WriteIndexToFile(*Index, OS);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000573 }
574
575 // Prepare the resulting object vector
576 assert(ProducedBinaries.empty() && "The generator should not be reused");
577 ProducedBinaries.resize(Modules.size());
578
579 // Prepare the module map.
580 auto ModuleMap = generateModuleMap(Modules);
Mehdi Amini01e32132016-03-26 05:40:34 +0000581 auto ModuleCount = Modules.size();
582
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000583 // Collect for each module the list of function it defines (GUID -> Summary).
584 StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
585 ModuleToDefinedGVSummaries(ModuleCount);
586 Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
587
Mehdi Amini01e32132016-03-26 05:40:34 +0000588 // Collect the import/export lists for all modules from the call-graph in the
589 // combined index.
590 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
591 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000592 ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists,
593 ExportLists);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000594
595 // Parallel optimizer + codegen
596 {
597 ThreadPool Pool(ThreadCount);
598 int count = 0;
599 for (auto &ModuleBuffer : Modules) {
600 Pool.async([&](int count) {
601 LLVMContext Context;
Mehdi Amini09b4a8d2016-03-10 01:28:54 +0000602 Context.setDiscardValueNames(LTODiscardValueNames);
Teresa Johnson07c7e252016-04-19 15:48:30 +0000603 Context.enableDebugTypeODRUniquing();
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000604 auto ModuleIdentifier = ModuleBuffer.getBufferIdentifier();
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000605 auto &ExportList = ExportLists[ModuleIdentifier];
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000606
607 DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR;
Mehdi Aminia71a5a62016-04-21 05:47:17 +0000608 ResolveODR(*Index, ExportList,
609 ModuleToDefinedGVSummaries[ModuleIdentifier],
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000610 ModuleIdentifier, ResolvedODR);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000611
612 // Parse module now
613 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
614
615 // Save temps: original file.
616 if (!SaveTempsDir.empty()) {
617 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
618 }
619
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000620 auto &ImportList = ImportLists[ModuleIdentifier];
Mehdi Amini024a79f2016-04-02 05:08:18 +0000621 ProducedBinaries[count] = ProcessThinLTOModule(
Mehdi Amini01e32132016-03-26 05:40:34 +0000622 *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
Mehdi Amini1aafabf2016-04-16 07:02:16 +0000623 ResolvedODR, CacheOptions, DisableCodeGen, SaveTempsDir, count);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000624 }, count);
625 count++;
626 }
627 }
628
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000629 // If statistics were requested, print them out now.
630 if (llvm::AreStatisticsEnabled())
631 llvm::PrintStatistics();
632}