summaryrefslogtreecommitdiff
path: root/lld/ELF/LTO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/LTO.cpp')
-rw-r--r--lld/ELF/LTO.cpp103
1 files changed, 75 insertions, 28 deletions
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 2148ac500291..b8041afed6c9 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -41,9 +41,8 @@
using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;
-
-namespace lld {
-namespace elf {
+using namespace lld;
+using namespace lld::elf;
// Creates an empty file to store a list of object files for final
// linking of distributed ThinLTO.
@@ -59,9 +58,9 @@ static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
}
static std::string getThinLTOOutputFile(StringRef modulePath) {
- return lto::getThinLTOOutputFile(modulePath,
- config->thinLTOPrefixReplace.first,
- config->thinLTOPrefixReplace.second);
+ return lto::getThinLTOOutputFile(
+ std::string(modulePath), std::string(config->thinLTOPrefixReplace.first),
+ std::string(config->thinLTOPrefixReplace.second));
}
static lto::Config createConfig() {
@@ -76,6 +75,33 @@ static lto::Config createConfig() {
c.Options.FunctionSections = true;
c.Options.DataSections = true;
+ // Check if basic block sections must be used.
+ // Allowed values for --lto-basicblock-sections are "all", "labels",
+ // "<file name specifying basic block ids>", or none. This is the equivalent
+ // of -fbasic-block-sections= flag in clang.
+ if (!config->ltoBasicBlockSections.empty()) {
+ if (config->ltoBasicBlockSections == "all") {
+ c.Options.BBSections = BasicBlockSection::All;
+ } else if (config->ltoBasicBlockSections == "labels") {
+ c.Options.BBSections = BasicBlockSection::Labels;
+ } else if (config->ltoBasicBlockSections == "none") {
+ c.Options.BBSections = BasicBlockSection::None;
+ } else {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
+ MemoryBuffer::getFile(config->ltoBasicBlockSections.str());
+ if (!MBOrErr) {
+ error("cannot open " + config->ltoBasicBlockSections + ":" +
+ MBOrErr.getError().message());
+ } else {
+ c.Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
+ }
+ c.Options.BBSections = BasicBlockSection::List;
+ }
+ }
+
+ c.Options.UniqueBasicBlockSectionNames =
+ config->ltoUniqueBasicBlockSectionNames;
+
if (auto relocModel = getRelocModelFromCMModel())
c.RelocModel = *relocModel;
else if (config->relocatable)
@@ -97,21 +123,30 @@ static lto::Config createConfig() {
c.PTO.SLPVectorization = c.OptLevel > 1;
// Set up a custom pipeline if we've been asked to.
- c.OptPipeline = config->ltoNewPmPasses;
- c.AAPipeline = config->ltoAAPipeline;
+ c.OptPipeline = std::string(config->ltoNewPmPasses);
+ c.AAPipeline = std::string(config->ltoAAPipeline);
// Set up optimization remarks if we've been asked to.
- c.RemarksFilename = config->optRemarksFilename;
- c.RemarksPasses = config->optRemarksPasses;
+ c.RemarksFilename = std::string(config->optRemarksFilename);
+ c.RemarksPasses = std::string(config->optRemarksPasses);
c.RemarksWithHotness = config->optRemarksWithHotness;
- c.RemarksFormat = config->optRemarksFormat;
+ c.RemarksFormat = std::string(config->optRemarksFormat);
- c.SampleProfile = config->ltoSampleProfile;
+ c.SampleProfile = std::string(config->ltoSampleProfile);
c.UseNewPM = config->ltoNewPassManager;
c.DebugPassManager = config->ltoDebugPassManager;
- c.DwoDir = config->dwoDir;
+ c.DwoDir = std::string(config->dwoDir);
- c.CSIRProfile = config->ltoCSProfileFile;
+ c.HasWholeProgramVisibility = config->ltoWholeProgramVisibility;
+ c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();
+
+ for (const llvm::StringRef &name : config->thinLTOModulesToCompile)
+ c.ThinLTOModulesToCompile.emplace_back(name);
+
+ c.TimeTraceEnabled = config->timeTraceEnabled;
+ c.TimeTraceGranularity = config->timeTraceGranularity;
+
+ c.CSIRProfile = std::string(config->ltoCSProfileFile);
c.RunCSIRInstr = config->ltoCSProfileGenerate;
if (config->emitLLVM) {
@@ -122,6 +157,9 @@ static lto::Config createConfig() {
};
}
+ if (config->ltoEmitAsm)
+ c.CGFileType = CGFT_AssemblyFile;
+
if (config->saveTemps)
checkError(c.addSaveTemps(config->outputFile.str() + ".",
/*UseInputModulePath*/ true));
@@ -138,10 +176,12 @@ BitcodeCompiler::BitcodeCompiler() {
if (config->thinLTOIndexOnly) {
auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
backend = lto::createWriteIndexesThinBackend(
- config->thinLTOPrefixReplace.first, config->thinLTOPrefixReplace.second,
+ std::string(config->thinLTOPrefixReplace.first),
+ std::string(config->thinLTOPrefixReplace.second),
config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
- } else if (config->thinLTOJobs != -1U) {
- backend = lto::createInProcessThinBackend(config->thinLTOJobs);
+ } else {
+ backend = lto::createInProcessThinBackend(
+ llvm::heavyweight_hardware_concurrency(config->thinLTOJobs));
}
ltoObj = std::make_unique<lto::LTO>(createConfig(), backend,
@@ -218,7 +258,7 @@ void BitcodeCompiler::add(BitcodeFile &f) {
// distributed build system that depends on that behavior.
static void thinLTOCreateEmptyIndexFiles() {
for (LazyObjFile *f : lazyObjFiles) {
- if (!isBitcode(f->mb))
+ if (f->fetched || !isBitcode(f->mb))
continue;
std::string path = replaceThinLTOSuffix(getThinLTOOutputFile(f->getName()));
std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
@@ -259,12 +299,14 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
},
cache));
- // Emit empty index files for non-indexed files
- for (StringRef s : thinIndices) {
- std::string path = getThinLTOOutputFile(s);
- openFile(path + ".thinlto.bc");
- if (config->thinLTOEmitImportsFiles)
- openFile(path + ".imports");
+ // Emit empty index files for non-indexed files but not in single-module mode.
+ if (config->thinLTOModulesToCompile.empty()) {
+ for (StringRef s : thinIndices) {
+ std::string path = getThinLTOOutputFile(s);
+ openFile(path + ".thinlto.bc");
+ if (config->thinLTOEmitImportsFiles)
+ openFile(path + ".imports");
+ }
}
if (config->thinLTOIndexOnly) {
@@ -291,11 +333,19 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
}
if (config->saveTemps) {
- saveBuffer(buf[0], config->outputFile + ".lto.o");
+ if (!buf[0].empty())
+ saveBuffer(buf[0], config->outputFile + ".lto.o");
for (unsigned i = 1; i != maxTasks; ++i)
saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
}
+ if (config->ltoEmitAsm) {
+ saveBuffer(buf[0], config->outputFile);
+ for (unsigned i = 1; i != maxTasks; ++i)
+ saveBuffer(buf[i], config->outputFile + Twine(i));
+ return {};
+ }
+
std::vector<InputFile *> ret;
for (unsigned i = 0; i != maxTasks; ++i)
if (!buf[i].empty())
@@ -306,6 +356,3 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
ret.push_back(createObjectFile(*file));
return ret;
}
-
-} // namespace elf
-} // namespace lld