aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/LTO/LTOBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/LTO/LTOBackend.cpp')
-rw-r--r--contrib/llvm/lib/LTO/LTOBackend.cpp119
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));
}