diff options
Diffstat (limited to 'contrib/llvm/lib/LTO/LTOBackend.cpp')
-rw-r--r-- | contrib/llvm/lib/LTO/LTOBackend.cpp | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/contrib/llvm/lib/LTO/LTOBackend.cpp b/contrib/llvm/lib/LTO/LTOBackend.cpp index 501d6284117b..eadbb410bd5a 100644 --- a/contrib/llvm/lib/LTO/LTOBackend.cpp +++ b/contrib/llvm/lib/LTO/LTOBackend.cpp @@ -30,6 +30,10 @@ #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/ThreadPool.h" #include "llvm/Target/TargetMachine.h" @@ -72,17 +76,19 @@ Error Config::addSaveTemps(std::string OutputFileName, // user hasn't requested using the input module's path, emit to a file // named from the provided OutputFileName with the Task ID appended. if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) { - PathPrefix = OutputFileName + utostr(Task); + PathPrefix = OutputFileName; + if (Task != (unsigned)-1) + PathPrefix += utostr(Task) + "."; } else - PathPrefix = M.getModuleIdentifier(); - std::string Path = PathPrefix + "." + PathSuffix + ".bc"; + PathPrefix = M.getModuleIdentifier() + "."; + std::string Path = PathPrefix + PathSuffix + ".bc"; std::error_code EC; raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); // Because -save-temps is a debugging feature, we report the error // directly and exit. if (EC) reportOpenError(Path, EC.message()); - WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false); + WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false); return true; }; }; @@ -103,6 +109,12 @@ Error Config::addSaveTemps(std::string OutputFileName, if (EC) reportOpenError(Path, EC.message()); WriteIndexToFile(Index, OS); + + Path = OutputFileName + "index.dot"; + raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::F_None); + if (EC) + reportOpenError(Path, EC.message()); + Index.exportToDot(OSDot); return true; }; @@ -132,7 +144,9 @@ createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) { } static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM, - unsigned OptLevel, bool IsThinLTO) { + unsigned OptLevel, bool IsThinLTO, + ModuleSummaryIndex *ExportSummary, + const ModuleSummaryIndex *ImportSummary) { Optional<PGOOptions> PGOOpt; if (!Conf.SampleProfile.empty()) PGOOpt = PGOOptions("", "", Conf.SampleProfile, false, true); @@ -182,9 +196,10 @@ static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM, } if (IsThinLTO) - MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager); + MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager, + ImportSummary); else - MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager); + MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager, ExportSummary); MPM.run(Mod, MAM); // FIXME (davide): verify the output. @@ -267,7 +282,8 @@ bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod, runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline, Conf.DisableVerify); else if (Conf.UseNewPM) - runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO); + runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary, + ImportSummary); else runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary); return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod); @@ -278,11 +294,36 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream, if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod)) return; + std::unique_ptr<ToolOutputFile> DwoOut; + SmallString<1024> DwoFile(Conf.DwoPath); + if (!Conf.DwoDir.empty()) { + std::error_code EC; + if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir)) + report_fatal_error("Failed to create directory " + Conf.DwoDir + ": " + + EC.message()); + + DwoFile = Conf.DwoDir; + sys::path::append(DwoFile, std::to_string(Task) + ".dwo"); + } + + if (!DwoFile.empty()) { + std::error_code EC; + TM->Options.MCOptions.SplitDwarfFile = DwoFile.str().str(); + DwoOut = llvm::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::F_None); + if (EC) + report_fatal_error("Failed to open " + DwoFile + ": " + EC.message()); + } + auto Stream = AddStream(Task); legacy::PassManager CodeGenPasses; - if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, Conf.CGFileType)) + if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, + DwoOut ? &DwoOut->os() : nullptr, + Conf.CGFileType)) report_fatal_error("Failed to setup codegen"); CodeGenPasses.run(Mod); + + if (DwoOut) + DwoOut->keep(); } void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, @@ -303,7 +344,7 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, // FIXME: Provide a more direct way to do this in LLVM. SmallString<0> BC; raw_svector_ostream BCOS(BC); - WriteBitcodeToFile(MPart.get(), BCOS); + WriteBitcodeToFile(*MPart, BCOS); // Enqueue the task CodegenThreadPool.async( @@ -348,14 +389,15 @@ Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) { } -static void +static Error finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile) { // Make sure we flush the diagnostic remarks file in case the linker doesn't // call the global destructors before exiting. if (!DiagOutputFile) - return; + return Error::success(); DiagOutputFile->keep(); DiagOutputFile->os().flush(); + return Error::success(); } Error lto::backend(Config &C, AddStreamFn AddStream, @@ -377,10 +419,8 @@ Error lto::backend(Config &C, AddStreamFn AddStream, if (!C.CodeGenOnly) { if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false, - /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) { - finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); - return Error::success(); - } + /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); } if (ParallelCodeGenParallelismLevel == 1) { @@ -389,8 +429,28 @@ Error lto::backend(Config &C, AddStreamFn AddStream, splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel, std::move(Mod)); } - finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); +} + +static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals, + const ModuleSummaryIndex &Index) { + std::vector<GlobalValue*> DeadGVs; + for (auto &GV : Mod.global_values()) + if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID())) + if (!Index.isGlobalValueLive(GVS)) { + DeadGVs.push_back(&GV); + convertToDeclaration(GV); + } + + // Now that all dead bodies have been dropped, delete the actual objects + // themselves when possible. + for (GlobalValue *GV : DeadGVs) { + GV->removeDeadConstantUsers(); + // Might reference something defined in native object (i.e. dropped a + // non-prevailing IR def, but we need to keep the declaration). + if (GV->use_empty()) + GV->eraseFromParent(); + } } Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, @@ -404,27 +464,36 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod); + // Setup optimization remarks. + auto DiagFileOrErr = lto::setupOptimizationRemarks( + Mod.getContext(), Conf.RemarksFilename, Conf.RemarksWithHotness, Task); + if (!DiagFileOrErr) + return DiagFileOrErr.takeError(); + auto DiagnosticOutputFile = std::move(*DiagFileOrErr); + if (Conf.CodeGenOnly) { codegen(Conf, TM.get(), AddStream, Task, Mod); - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); } if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod)) - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); renameModuleForThinLTO(Mod, CombinedIndex); + dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex); + thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); if (!DefinedGlobals.empty()) thinLTOInternalizeModule(Mod, DefinedGlobals); if (Conf.PostInternalizeModuleHook && !Conf.PostInternalizeModuleHook(Task, Mod)) - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); auto ModuleLoader = [&](StringRef Identifier) { assert(Mod.getContext().isODRUniquingDebugTypes() && @@ -441,12 +510,12 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, return Err; if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod)) - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true, /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex)) - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); codegen(Conf, TM.get(), AddStream, Task, Mod); - return Error::success(); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); } |