blob: e437b4457d47d11ea5b1b7bd4c5c7aa141f9dd86 [file] [log] [blame]
Teresa Johnson9ba95f92016-08-11 14:58:12 +00001//===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Teresa Johnson9ba95f92016-08-11 14:58:12 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the "backend" phase of LTO, i.e. it performs
10// optimization and code generation on a loaded module. It is generally used
11// internally by the LTO class but can also be used independently, for example
12// to implement a standalone ThinLTO backend.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/LTO/LTOBackend.h"
Davide Italianoec9612d2016-09-07 17:46:16 +000017#include "llvm/Analysis/AliasAnalysis.h"
18#include "llvm/Analysis/CGSCCPassManager.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000019#include "llvm/Analysis/TargetLibraryInfo.h"
20#include "llvm/Analysis/TargetTransformInfo.h"
Teresa Johnsonad176792016-11-11 05:34:58 +000021#include "llvm/Bitcode/BitcodeReader.h"
22#include "llvm/Bitcode/BitcodeWriter.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000023#include "llvm/IR/LegacyPassManager.h"
Davide Italianoec9612d2016-09-07 17:46:16 +000024#include "llvm/IR/PassManager.h"
Francis Visoiu Mistrih7a211132019-06-14 16:20:51 +000025#include "llvm/IR/RemarkStreamer.h"
Davide Italianoec9612d2016-09-07 17:46:16 +000026#include "llvm/IR/Verifier.h"
Mehdi Amini970800e2016-08-17 06:23:09 +000027#include "llvm/LTO/LTO.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000028#include "llvm/MC/SubtargetFeature.h"
Peter Collingbourne192d8522017-03-28 23:35:34 +000029#include "llvm/Object/ModuleSymbolTable.h"
Davide Italianoec9612d2016-09-07 17:46:16 +000030#include "llvm/Passes/PassBuilder.h"
Taewook Oh213d8a92019-08-15 17:47:44 +000031#include "llvm/Passes/StandardInstrumentations.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000032#include "llvm/Support/Error.h"
33#include "llvm/Support/FileSystem.h"
Yunlian Jiangbd200b92018-04-13 05:03:28 +000034#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/Path.h"
36#include "llvm/Support/Program.h"
Teresa Johnsonc8e0bb32019-12-12 11:59:36 -080037#include "llvm/Support/SmallVectorMemoryBuffer.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000038#include "llvm/Support/TargetRegistry.h"
39#include "llvm/Support/ThreadPool.h"
Francis Visoiu Mistrih7a211132019-06-14 16:20:51 +000040#include "llvm/Support/raw_ostream.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000041#include "llvm/Target/TargetMachine.h"
42#include "llvm/Transforms/IPO.h"
43#include "llvm/Transforms/IPO/PassManagerBuilder.h"
Chandler Carruth3bab7e12017-01-11 09:43:56 +000044#include "llvm/Transforms/Scalar/LoopPassManager.h"
Teresa Johnson9ba95f92016-08-11 14:58:12 +000045#include "llvm/Transforms/Utils/FunctionImportUtils.h"
46#include "llvm/Transforms/Utils/SplitModule.h"
47
48using namespace llvm;
49using namespace lto;
50
Benjamin Kramer4c2582a2016-10-18 19:39:31 +000051LLVM_ATTRIBUTE_NORETURN static void reportOpenError(StringRef Path, Twine Msg) {
Davide Italianoa416d112016-09-17 22:32:42 +000052 errs() << "failed to open " << Path << ": " << Msg << '\n';
53 errs().flush();
54 exit(1);
55}
56
Teresa Johnson9ba95f92016-08-11 14:58:12 +000057Error Config::addSaveTemps(std::string OutputFileName,
58 bool UseInputModulePath) {
59 ShouldDiscardValueNames = false;
60
61 std::error_code EC;
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000062 ResolutionFile = std::make_unique<raw_fd_ostream>(
Fangrui Songd9b948b2019-08-05 05:43:48 +000063 OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::OF_Text);
Teresa Johnson9ba95f92016-08-11 14:58:12 +000064 if (EC)
65 return errorCodeToError(EC);
66
67 auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
68 // Keep track of the hook provided by the linker, which also needs to run.
69 ModuleHookFn LinkerHook = Hook;
Mehdi Aminif8c2f082016-08-22 16:17:40 +000070 Hook = [=](unsigned Task, const Module &M) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +000071 // If the linker's hook returned false, we need to pass that result
72 // through.
73 if (LinkerHook && !LinkerHook(Task, M))
74 return false;
75
76 std::string PathPrefix;
77 // If this is the combined module (not a ThinLTO backend compile) or the
78 // user hasn't requested using the input module's path, emit to a file
79 // named from the provided OutputFileName with the Task ID appended.
80 if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
Teresa Johnson81d92072018-05-05 14:37:20 +000081 PathPrefix = OutputFileName;
82 if (Task != (unsigned)-1)
83 PathPrefix += utostr(Task) + ".";
Teresa Johnson9ba95f92016-08-11 14:58:12 +000084 } else
Teresa Johnson81d92072018-05-05 14:37:20 +000085 PathPrefix = M.getModuleIdentifier() + ".";
86 std::string Path = PathPrefix + PathSuffix + ".bc";
Teresa Johnson9ba95f92016-08-11 14:58:12 +000087 std::error_code EC;
Fangrui Songd9b948b2019-08-05 05:43:48 +000088 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
Davide Italianoa416d112016-09-17 22:32:42 +000089 // Because -save-temps is a debugging feature, we report the error
90 // directly and exit.
91 if (EC)
92 reportOpenError(Path, EC.message());
Rafael Espindola6a86e252018-02-14 19:11:32 +000093 WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false);
Teresa Johnson9ba95f92016-08-11 14:58:12 +000094 return true;
95 };
96 };
97
98 setHook("0.preopt", PreOptModuleHook);
99 setHook("1.promote", PostPromoteModuleHook);
100 setHook("2.internalize", PostInternalizeModuleHook);
101 setHook("3.import", PostImportModuleHook);
102 setHook("4.opt", PostOptModuleHook);
103 setHook("5.precodegen", PreCodeGenModuleHook);
104
105 CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
Mehdi Aminieccffad2016-08-18 00:12:33 +0000106 std::string Path = OutputFileName + "index.bc";
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000107 std::error_code EC;
Fangrui Songd9b948b2019-08-05 05:43:48 +0000108 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
Davide Italianoa416d112016-09-17 22:32:42 +0000109 // Because -save-temps is a debugging feature, we report the error
110 // directly and exit.
111 if (EC)
112 reportOpenError(Path, EC.message());
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000113 WriteIndexToFile(Index, OS);
Eugene Leviant28d8a492018-01-22 13:35:40 +0000114
115 Path = OutputFileName + "index.dot";
Fangrui Songd9b948b2019-08-05 05:43:48 +0000116 raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::OF_None);
Eugene Leviant28d8a492018-01-22 13:35:40 +0000117 if (EC)
118 reportOpenError(Path, EC.message());
119 Index.exportToDot(OSDot);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000120 return true;
121 };
122
Mehdi Amini41af4302016-11-11 04:28:40 +0000123 return Error::success();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000124}
125
126namespace {
127
128std::unique_ptr<TargetMachine>
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000129createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
130 StringRef TheTriple = M.getTargetTriple();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000131 SubtargetFeatures Features;
132 Features.getDefaultSubtargetFeatures(Triple(TheTriple));
Davide Italiano24c29b12016-09-07 01:08:31 +0000133 for (const std::string &A : Conf.MAttrs)
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000134 Features.AddFeature(A);
135
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000136 Reloc::Model RelocModel;
137 if (Conf.RelocModel)
138 RelocModel = *Conf.RelocModel;
139 else
140 RelocModel =
141 M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
142
Caroline Tice3dea3f92018-09-21 18:41:31 +0000143 Optional<CodeModel::Model> CodeModel;
144 if (Conf.CodeModel)
145 CodeModel = *Conf.CodeModel;
146 else
147 CodeModel = M.getCodeModel();
148
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000149 return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000150 TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
Caroline Tice3dea3f92018-09-21 18:41:31 +0000151 CodeModel, Conf.CGOptLevel));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000152}
153
Dehao Chen89d32262017-08-02 01:28:31 +0000154static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
Teresa Johnson28023db2018-07-19 14:51:32 +0000155 unsigned OptLevel, bool IsThinLTO,
156 ModuleSummaryIndex *ExportSummary,
157 const ModuleSummaryIndex *ImportSummary) {
Dehao Chen89d32262017-08-02 01:28:31 +0000158 Optional<PGOOptions> PGOOpt;
159 if (!Conf.SampleProfile.empty())
Rong Xudb29a3a2019-03-04 20:21:27 +0000160 PGOOpt = PGOOptions(Conf.SampleProfile, "", Conf.ProfileRemapping,
161 PGOOptions::SampleUse, PGOOptions::NoCSAction, true);
162 else if (Conf.RunCSIRInstr) {
163 PGOOpt = PGOOptions("", Conf.CSIRProfile, Conf.ProfileRemapping,
164 PGOOptions::IRUse, PGOOptions::CSIRInstr);
165 } else if (!Conf.CSIRProfile.empty()) {
166 PGOOpt = PGOOptions(Conf.CSIRProfile, "", Conf.ProfileRemapping,
167 PGOOptions::IRUse, PGOOptions::CSIRUse);
168 }
Dehao Chen89d32262017-08-02 01:28:31 +0000169
Taewook Oh213d8a92019-08-15 17:47:44 +0000170 PassInstrumentationCallbacks PIC;
171 StandardInstrumentations SI;
172 SI.registerCallbacks(PIC);
173 PassBuilder PB(TM, PipelineTuningOptions(),PGOOpt, &PIC);
Davide Italiano0dd200e2017-01-24 00:58:24 +0000174 AAManager AA;
175
176 // Parse a custom AA pipeline if asked to.
Fedor Sergeevbd6b2132018-10-17 10:36:23 +0000177 if (auto Err = PB.parseAAPipeline(AA, "default"))
Dehao Chen3246dc32017-08-02 03:03:19 +0000178 report_fatal_error("Error parsing default AA pipeline");
Davide Italiano0dd200e2017-01-24 00:58:24 +0000179
Dehao Chen3246dc32017-08-02 03:03:19 +0000180 LoopAnalysisManager LAM(Conf.DebugPassManager);
181 FunctionAnalysisManager FAM(Conf.DebugPassManager);
182 CGSCCAnalysisManager CGAM(Conf.DebugPassManager);
183 ModuleAnalysisManager MAM(Conf.DebugPassManager);
Davide Italiano0dd200e2017-01-24 00:58:24 +0000184
185 // Register the AA manager first so that our version is the one used.
186 FAM.registerPass([&] { return std::move(AA); });
187
188 // Register all the basic analyses with the managers.
189 PB.registerModuleAnalyses(MAM);
190 PB.registerCGSCCAnalyses(CGAM);
191 PB.registerFunctionAnalyses(FAM);
192 PB.registerLoopAnalyses(LAM);
193 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
194
Dehao Chen3246dc32017-08-02 03:03:19 +0000195 ModulePassManager MPM(Conf.DebugPassManager);
Davide Italiano0dd200e2017-01-24 00:58:24 +0000196 // FIXME (davide): verify the input.
197
198 PassBuilder::OptimizationLevel OL;
199
200 switch (OptLevel) {
201 default:
202 llvm_unreachable("Invalid optimization level");
203 case 0:
204 OL = PassBuilder::O0;
205 break;
206 case 1:
207 OL = PassBuilder::O1;
208 break;
209 case 2:
210 OL = PassBuilder::O2;
211 break;
212 case 3:
213 OL = PassBuilder::O3;
214 break;
215 }
216
Chandler Carruth8b3be4e2017-06-01 11:39:39 +0000217 if (IsThinLTO)
Teresa Johnson28023db2018-07-19 14:51:32 +0000218 MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager,
219 ImportSummary);
Chandler Carruth8b3be4e2017-06-01 11:39:39 +0000220 else
Teresa Johnson28023db2018-07-19 14:51:32 +0000221 MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager, ExportSummary);
Davide Italiano0dd200e2017-01-24 00:58:24 +0000222 MPM.run(Mod, MAM);
223
224 // FIXME (davide): verify the output.
225}
226
Davide Italianoec9612d2016-09-07 17:46:16 +0000227static void runNewPMCustomPasses(Module &Mod, TargetMachine *TM,
228 std::string PipelineDesc,
Davide Italiano14e9e8a2016-09-16 21:03:21 +0000229 std::string AAPipelineDesc,
Davide Italianoec9612d2016-09-07 17:46:16 +0000230 bool DisableVerify) {
231 PassBuilder PB(TM);
232 AAManager AA;
Davide Italiano14e9e8a2016-09-16 21:03:21 +0000233
234 // Parse a custom AA pipeline if asked to.
235 if (!AAPipelineDesc.empty())
Fedor Sergeevbd6b2132018-10-17 10:36:23 +0000236 if (auto Err = PB.parseAAPipeline(AA, AAPipelineDesc))
237 report_fatal_error("unable to parse AA pipeline description '" +
238 AAPipelineDesc + "': " + toString(std::move(Err)));
Davide Italiano14e9e8a2016-09-16 21:03:21 +0000239
Davide Italianoec9612d2016-09-07 17:46:16 +0000240 LoopAnalysisManager LAM;
241 FunctionAnalysisManager FAM;
242 CGSCCAnalysisManager CGAM;
243 ModuleAnalysisManager MAM;
244
245 // Register the AA manager first so that our version is the one used.
246 FAM.registerPass([&] { return std::move(AA); });
247
248 // Register all the basic analyses with the managers.
249 PB.registerModuleAnalyses(MAM);
250 PB.registerCGSCCAnalyses(CGAM);
251 PB.registerFunctionAnalyses(FAM);
252 PB.registerLoopAnalyses(LAM);
253 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
254
255 ModulePassManager MPM;
256
257 // Always verify the input.
258 MPM.addPass(VerifierPass());
259
260 // Now, add all the passes we've been requested to.
Fedor Sergeevbd6b2132018-10-17 10:36:23 +0000261 if (auto Err = PB.parsePassPipeline(MPM, PipelineDesc))
262 report_fatal_error("unable to parse pass pipeline description '" +
263 PipelineDesc + "': " + toString(std::move(Err)));
Davide Italianoec9612d2016-09-07 17:46:16 +0000264
265 if (!DisableVerify)
266 MPM.addPass(VerifierPass());
267 MPM.run(Mod, MAM);
268}
269
Davide Italiano24c29b12016-09-07 01:08:31 +0000270static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
Peter Collingbournef7691d82017-03-22 18:22:59 +0000271 bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
272 const ModuleSummaryIndex *ImportSummary) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000273 legacy::PassManager passes;
274 passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
275
276 PassManagerBuilder PMB;
277 PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
278 PMB.Inliner = createFunctionInliningPass();
Peter Collingbournef7691d82017-03-22 18:22:59 +0000279 PMB.ExportSummary = ExportSummary;
280 PMB.ImportSummary = ImportSummary;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000281 // Unconditionally verify input since it is not verified before this
282 // point and has unknown origin.
283 PMB.VerifyInput = true;
Davide Italiano24c29b12016-09-07 01:08:31 +0000284 PMB.VerifyOutput = !Conf.DisableVerify;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000285 PMB.LoopVectorize = true;
286 PMB.SLPVectorize = true;
Davide Italiano24c29b12016-09-07 01:08:31 +0000287 PMB.OptLevel = Conf.OptLevel;
Dehao Chen27978002016-12-16 16:48:46 +0000288 PMB.PGOSampleUse = Conf.SampleProfile;
Rong Xudb29a3a2019-03-04 20:21:27 +0000289 PMB.EnablePGOCSInstrGen = Conf.RunCSIRInstr;
290 if (!Conf.RunCSIRInstr && !Conf.CSIRProfile.empty()) {
291 PMB.EnablePGOCSInstrUse = true;
292 PMB.PGOInstrUse = Conf.CSIRProfile;
293 }
Davide Italiano8812f282016-11-24 00:23:09 +0000294 if (IsThinLTO)
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000295 PMB.populateThinLTOPassManager(passes);
296 else
297 PMB.populateLTOPassManager(passes);
Davide Italiano24c29b12016-09-07 01:08:31 +0000298 passes.run(Mod);
Davide Italiano1e9d3d32016-08-31 17:02:44 +0000299}
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000300
Davide Italiano24c29b12016-09-07 01:08:31 +0000301bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
Peter Collingbournef7691d82017-03-22 18:22:59 +0000302 bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
303 const ModuleSummaryIndex *ImportSummary) {
Davide Italiano0dd200e2017-01-24 00:58:24 +0000304 // FIXME: Plumb the combined index into the new pass manager.
305 if (!Conf.OptPipeline.empty())
Davide Italiano14e9e8a2016-09-16 21:03:21 +0000306 runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
307 Conf.DisableVerify);
Tim Shen4e912aa2017-06-01 23:13:44 +0000308 else if (Conf.UseNewPM)
Teresa Johnson28023db2018-07-19 14:51:32 +0000309 runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
310 ImportSummary);
Davide Italiano0dd200e2017-01-24 00:58:24 +0000311 else
Peter Collingbournef7691d82017-03-22 18:22:59 +0000312 runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
Davide Italiano24c29b12016-09-07 01:08:31 +0000313 return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000314}
315
Teresa Johnsonc8e0bb32019-12-12 11:59:36 -0800316static cl::opt<bool> EmbedBitcode(
317 "lto-embed-bitcode", cl::init(false),
318 cl::desc("Embed LLVM bitcode in object files produced by LTO"));
319
320static void EmitBitcodeSection(Module &M, Config &Conf) {
321 if (!EmbedBitcode)
322 return;
323 SmallVector<char, 0> Buffer;
324 raw_svector_ostream OS(Buffer);
325 WriteBitcodeToFile(M, OS);
326
327 std::unique_ptr<MemoryBuffer> Buf(
328 new SmallVectorMemoryBuffer(std::move(Buffer)));
329 llvm::EmbedBitcodeInModule(M, Buf->getMemBufferRef(), /*EmbedBitcode*/ true,
330 /*EmbedMarker*/ false, /*CmdArgs*/ nullptr);
331}
332
Peter Collingbourne80186a52016-09-23 21:33:43 +0000333void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
Davide Italiano24c29b12016-09-07 01:08:31 +0000334 unsigned Task, Module &Mod) {
335 if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000336 return;
337
Teresa Johnsonc8e0bb32019-12-12 11:59:36 -0800338 EmitBitcodeSection(Mod, Conf);
339
Peter Collingbournec5a97652018-05-21 20:26:49 +0000340 std::unique_ptr<ToolOutputFile> DwoOut;
Aaron Pucherte1dc4952019-06-15 15:38:51 +0000341 SmallString<1024> DwoFile(Conf.SplitDwarfOutput);
Yunlian Jiangbd200b92018-04-13 05:03:28 +0000342 if (!Conf.DwoDir.empty()) {
Peter Collingbournec5a97652018-05-21 20:26:49 +0000343 std::error_code EC;
344 if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
345 report_fatal_error("Failed to create directory " + Conf.DwoDir + ": " +
346 EC.message());
347
Peter Collingbourne3aa30e82018-05-31 18:25:59 +0000348 DwoFile = Conf.DwoDir;
Peter Collingbournec5a97652018-05-21 20:26:49 +0000349 sys::path::append(DwoFile, std::to_string(Task) + ".dwo");
Aaron Pucherte1dc4952019-06-15 15:38:51 +0000350 TM->Options.MCOptions.SplitDwarfFile = DwoFile.str().str();
351 } else
352 TM->Options.MCOptions.SplitDwarfFile = Conf.SplitDwarfFile;
Peter Collingbourne3aa30e82018-05-31 18:25:59 +0000353
354 if (!DwoFile.empty()) {
355 std::error_code EC;
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000356 DwoOut = std::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::OF_None);
Peter Collingbournec5a97652018-05-21 20:26:49 +0000357 if (EC)
358 report_fatal_error("Failed to open " + DwoFile + ": " + EC.message());
Yunlian Jiangbd200b92018-04-13 05:03:28 +0000359 }
360
Peter Collingbourne80186a52016-09-23 21:33:43 +0000361 auto Stream = AddStream(Task);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000362 legacy::PassManager CodeGenPasses;
Peter Collingbournec5a97652018-05-21 20:26:49 +0000363 if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
364 DwoOut ? &DwoOut->os() : nullptr,
Peter Collingbourne9a451142018-05-21 20:16:41 +0000365 Conf.CGFileType))
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000366 report_fatal_error("Failed to setup codegen");
Davide Italiano24c29b12016-09-07 01:08:31 +0000367 CodeGenPasses.run(Mod);
Peter Collingbournec5a97652018-05-21 20:26:49 +0000368
369 if (DwoOut)
370 DwoOut->keep();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000371}
372
Peter Collingbourne80186a52016-09-23 21:33:43 +0000373void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000374 unsigned ParallelCodeGenParallelismLevel,
Davide Italiano24c29b12016-09-07 01:08:31 +0000375 std::unique_ptr<Module> Mod) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000376 ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
377 unsigned ThreadCount = 0;
378 const Target *T = &TM->getTarget();
379
380 SplitModule(
Davide Italiano24c29b12016-09-07 01:08:31 +0000381 std::move(Mod), ParallelCodeGenParallelismLevel,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000382 [&](std::unique_ptr<Module> MPart) {
383 // We want to clone the module in a new context to multi-thread the
384 // codegen. We do it by serializing partition modules to bitcode
385 // (while still on the main thread, in order to avoid data races) and
386 // spinning up new threads which deserialize the partitions into
387 // separate contexts.
388 // FIXME: Provide a more direct way to do this in LLVM.
389 SmallString<0> BC;
390 raw_svector_ostream BCOS(BC);
Rafael Espindola6a86e252018-02-14 19:11:32 +0000391 WriteBitcodeToFile(*MPart, BCOS);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000392
393 // Enqueue the task
394 CodegenThreadPool.async(
395 [&](const SmallString<0> &BC, unsigned ThreadId) {
396 LTOLLVMContext Ctx(C);
Peter Collingbourned9445c42016-11-13 07:00:17 +0000397 Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000398 MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
399 Ctx);
400 if (!MOrErr)
401 report_fatal_error("Failed to read bitcode");
402 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
403
404 std::unique_ptr<TargetMachine> TM =
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000405 createTargetMachine(C, T, *MPartInCtx);
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000406
Peter Collingbourne80186a52016-09-23 21:33:43 +0000407 codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000408 },
409 // Pass BC using std::move to ensure that it get moved rather than
410 // copied into the thread's context.
411 std::move(BC), ThreadCount++);
412 },
413 false);
Peter Collingbournef75609e2016-09-29 03:29:28 +0000414
415 // Because the inner lambda (which runs in a worker thread) captures our local
416 // variables, we need to wait for the worker threads to terminate before we
417 // can leave the function scope.
Peter Collingbourne0d5636e2016-09-29 01:28:36 +0000418 CodegenThreadPool.wait();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000419}
420
Davide Italiano24c29b12016-09-07 01:08:31 +0000421Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000422 if (!C.OverrideTriple.empty())
Davide Italiano24c29b12016-09-07 01:08:31 +0000423 Mod.setTargetTriple(C.OverrideTriple);
424 else if (Mod.getTargetTriple().empty())
425 Mod.setTargetTriple(C.DefaultTriple);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000426
427 std::string Msg;
Davide Italiano24c29b12016-09-07 01:08:31 +0000428 const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000429 if (!T)
430 return make_error<StringError>(Msg, inconvertibleErrorCode());
431 return T;
432}
433
434}
435
Teresa Johnson85cc2982018-05-03 20:24:12 +0000436static Error
Reid Kleckner3fc649c2017-09-23 01:03:17 +0000437finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile) {
Davide Italiano20a895c2017-02-13 14:39:51 +0000438 // Make sure we flush the diagnostic remarks file in case the linker doesn't
439 // call the global destructors before exiting.
440 if (!DiagOutputFile)
Teresa Johnson85cc2982018-05-03 20:24:12 +0000441 return Error::success();
Davide Italiano20a895c2017-02-13 14:39:51 +0000442 DiagOutputFile->keep();
443 DiagOutputFile->os().flush();
Teresa Johnson85cc2982018-05-03 20:24:12 +0000444 return Error::success();
Davide Italiano20a895c2017-02-13 14:39:51 +0000445}
446
Peter Collingbourne80186a52016-09-23 21:33:43 +0000447Error lto::backend(Config &C, AddStreamFn AddStream,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000448 unsigned ParallelCodeGenParallelismLevel,
Peter Collingbournee02b74e2017-01-20 22:18:52 +0000449 std::unique_ptr<Module> Mod,
450 ModuleSummaryIndex &CombinedIndex) {
Davide Italiano24c29b12016-09-07 01:08:31 +0000451 Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000452 if (!TOrErr)
453 return TOrErr.takeError();
454
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000455 std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000456
Davide Italianoebd47192017-02-12 03:31:30 +0000457 // Setup optimization remarks.
Francis Visoiu Mistrih34667512019-06-17 16:06:00 +0000458 auto DiagFileOrErr = lto::setupOptimizationRemarks(
459 Mod->getContext(), C.RemarksFilename, C.RemarksPasses, C.RemarksFormat,
460 C.RemarksWithHotness);
Davide Italianoebd47192017-02-12 03:31:30 +0000461 if (!DiagFileOrErr)
462 return DiagFileOrErr.takeError();
Davide Italiano20a895c2017-02-13 14:39:51 +0000463 auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
Davide Italianoebd47192017-02-12 03:31:30 +0000464
Davide Italiano20a895c2017-02-13 14:39:51 +0000465 if (!C.CodeGenOnly) {
Peter Collingbournef7691d82017-03-22 18:22:59 +0000466 if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
Teresa Johnson85cc2982018-05-03 20:24:12 +0000467 /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
468 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Davide Italiano20a895c2017-02-13 14:39:51 +0000469 }
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000470
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000471 if (ParallelCodeGenParallelismLevel == 1) {
Peter Collingbourne80186a52016-09-23 21:33:43 +0000472 codegen(C, TM.get(), AddStream, 0, *Mod);
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000473 } else {
Peter Collingbourne80186a52016-09-23 21:33:43 +0000474 splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
Davide Italiano24c29b12016-09-07 01:08:31 +0000475 std::move(Mod));
Mehdi Aminiadc0e262016-08-23 21:30:12 +0000476 }
Teresa Johnson85cc2982018-05-03 20:24:12 +0000477 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000478}
479
George Rimareaf51722018-01-29 08:03:30 +0000480static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
481 const ModuleSummaryIndex &Index) {
Teresa Johnson791c98e2018-02-06 00:43:39 +0000482 std::vector<GlobalValue*> DeadGVs;
Teresa Johnson5a95c472018-02-05 15:44:27 +0000483 for (auto &GV : Mod.global_values())
George Rimarf5de2712018-02-02 12:21:26 +0000484 if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
Teresa Johnson791c98e2018-02-06 00:43:39 +0000485 if (!Index.isGlobalValueLive(GVS)) {
486 DeadGVs.push_back(&GV);
487 convertToDeclaration(GV);
488 }
George Rimar76c5fae2018-02-02 12:17:33 +0000489
Teresa Johnson791c98e2018-02-06 00:43:39 +0000490 // Now that all dead bodies have been dropped, delete the actual objects
491 // themselves when possible.
492 for (GlobalValue *GV : DeadGVs) {
493 GV->removeDeadConstantUsers();
494 // Might reference something defined in native object (i.e. dropped a
495 // non-prevailing IR def, but we need to keep the declaration).
496 if (GV->use_empty())
497 GV->eraseFromParent();
498 }
George Rimareaf51722018-01-29 08:03:30 +0000499}
500
Peter Collingbourne80186a52016-09-23 21:33:43 +0000501Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
Peter Collingbournef7691d82017-03-22 18:22:59 +0000502 Module &Mod, const ModuleSummaryIndex &CombinedIndex,
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000503 const FunctionImporter::ImportMapTy &ImportList,
504 const GVSummaryMapTy &DefinedGlobals,
Peter Collingbourne1a0720e2016-12-14 01:17:59 +0000505 MapVector<StringRef, BitcodeModule> &ModuleMap) {
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000506 Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000507 if (!TOrErr)
508 return TOrErr.takeError();
509
Evgeniy Stepanovb9f1b012017-05-22 21:11:35 +0000510 std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000511
Teresa Johnson85cc2982018-05-03 20:24:12 +0000512 // Setup optimization remarks.
513 auto DiagFileOrErr = lto::setupOptimizationRemarks(
Francis Visoiu Mistrihdd422362019-03-12 21:22:27 +0000514 Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
Francis Visoiu Mistrih34667512019-06-17 16:06:00 +0000515 Conf.RemarksFormat, Conf.RemarksWithHotness, Task);
Teresa Johnson85cc2982018-05-03 20:24:12 +0000516 if (!DiagFileOrErr)
517 return DiagFileOrErr.takeError();
518 auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
519
Mehdi Aminid310b472016-08-22 06:25:41 +0000520 if (Conf.CodeGenOnly) {
Peter Collingbourne80186a52016-09-23 21:33:43 +0000521 codegen(Conf, TM.get(), AddStream, Task, Mod);
Teresa Johnson85cc2982018-05-03 20:24:12 +0000522 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Mehdi Aminid310b472016-08-22 06:25:41 +0000523 }
524
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000525 if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
Teresa Johnson85cc2982018-05-03 20:24:12 +0000526 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000527
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000528 renameModuleForThinLTO(Mod, CombinedIndex);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000529
George Rimareaf51722018-01-29 08:03:30 +0000530 dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex);
531
Pirama Arumuga Nainare61652a2018-11-08 20:10:07 +0000532 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
Mehdi Amini8ac7b322016-08-18 00:59:24 +0000533
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000534 if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
Teresa Johnson85cc2982018-05-03 20:24:12 +0000535 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000536
537 if (!DefinedGlobals.empty())
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000538 thinLTOInternalizeModule(Mod, DefinedGlobals);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000539
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000540 if (Conf.PostInternalizeModuleHook &&
541 !Conf.PostInternalizeModuleHook(Task, Mod))
Teresa Johnson85cc2982018-05-03 20:24:12 +0000542 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000543
544 auto ModuleLoader = [&](StringRef Identifier) {
Mehdi Amini9ec5a612016-08-23 16:53:34 +0000545 assert(Mod.getContext().isODRUniquingDebugTypes() &&
Davide Italiano63e8f442016-09-14 18:48:43 +0000546 "ODR Type uniquing should be enabled on the context");
Peter Collingbourne1a0720e2016-12-14 01:17:59 +0000547 auto I = ModuleMap.find(Identifier);
548 assert(I != ModuleMap.end());
549 return I->second.getLazyModule(Mod.getContext(),
Teresa Johnsona61f5e32016-12-16 21:25:01 +0000550 /*ShouldLazyLoadMetadata=*/true,
551 /*IsImporting*/ true);
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000552 };
553
554 FunctionImporter Importer(CombinedIndex, ModuleLoader);
Peter Collingbourne7f00d0a2016-11-09 17:49:19 +0000555 if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
556 return Err;
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000557
Mehdi Aminiacc50c42016-08-16 00:44:46 +0000558 if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
Teresa Johnson85cc2982018-05-03 20:24:12 +0000559 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000560
Peter Collingbournef7691d82017-03-22 18:22:59 +0000561 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
562 /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
Teresa Johnson85cc2982018-05-03 20:24:12 +0000563 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000564
Peter Collingbourne80186a52016-09-23 21:33:43 +0000565 codegen(Conf, TM.get(), AddStream, Task, Mod);
Teresa Johnson85cc2982018-05-03 20:24:12 +0000566 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000567}