From 5fd2c900e90445c6efb7b97f8c663e588bcab81b Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton@redhat.com>
Date: Tue, 2 Jul 2019 09:25:52 +0000
Subject: [PATCH] Selectively disable threading from gold
Related: rhbz#1636479
---
llvm/include/llvm/LTO/LTO.h | 3 +
llvm/include/llvm/LTO/LTOBackend.h | 3 +
llvm/include/llvm/Support/ThreadPool.h | 7 ++
llvm/lib/LTO/LTO.cpp | 134 ++++++++++++++++++++++++-
llvm/lib/LTO/LTOBackend.cpp | 48 ++++++++-
llvm/lib/Support/ThreadPool.cpp | 6 +-
llvm/tools/gold/gold-plugin.cpp | 7 +-
7 files changed, 197 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 534d9b6f3f2..9dfda126540 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -212,6 +212,7 @@ typedef std::function<std::unique_ptr<ThinBackendProc>(
/// This ThinBackend runs the individual backend jobs in-process.
ThinBackend createInProcessThinBackend(unsigned ParallelismLevel);
+ThinBackend createInProcessThinBackendNoThread(unsigned ParallelismLevel);
/// This ThinBackend writes individual module indexes to files, instead of
/// running the individual backend jobs. This backend is for distributed builds
@@ -281,6 +282,7 @@ public:
/// The client will receive at most one callback (via either AddStream or
/// Cache) for each task identifier.
Error run(AddStreamFn AddStream, NativeObjectCache Cache = nullptr);
+ Error runNoThread(AddStreamFn AddStream, NativeObjectCache Cache = nullptr);
private:
Config Conf;
@@ -397,6 +399,7 @@ private:
const SymbolResolution *&ResI, const SymbolResolution *ResE);
Error runRegularLTO(AddStreamFn AddStream);
+ Error runRegularLTONoThread(AddStreamFn AddStream);
Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache);
mutable bool CalledGetMaxTasks = false;
diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h
index d4743f6940f..2d6461fa82e 100644
--- a/llvm/include/llvm/LTO/LTOBackend.h
+++ b/llvm/include/llvm/LTO/LTOBackend.h
@@ -39,6 +39,9 @@ namespace lto {
Error backend(Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel,
std::unique_ptr<Module> M, ModuleSummaryIndex &CombinedIndex);
+Error backendNoThread(Config &C, AddStreamFn AddStream,
+ unsigned ParallelCodeGenParallelismLevel,
+ std::unique_ptr<Module> M, ModuleSummaryIndex &CombinedIndex);
/// Runs a ThinLTO backend.
Error thinBackend(Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
diff --git a/llvm/include/llvm/Support/ThreadPool.h b/llvm/include/llvm/Support/ThreadPool.h
index 4fdbd528b21..60ea5097114 100644
--- a/llvm/include/llvm/Support/ThreadPool.h
+++ b/llvm/include/llvm/Support/ThreadPool.h
@@ -98,4 +98,11 @@ private:
};
}
+#ifndef ThreadPool
+#undef LLVM_SUPPORT_THREAD_POOL_H
+#define ThreadPool SequentialThreadPool
+#include "llvm/Support/ThreadPool.h"
+#undef ThreadPool
+#endif
+
#endif // LLVM_SUPPORT_THREAD_POOL_H
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 3a955060dea..a7b4f45b18c 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -861,6 +861,58 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
return Result;
}
+Error LTO::runNoThread(AddStreamFn AddStream, NativeObjectCache Cache) {
+ // Compute "dead" symbols, we don't want to import/export these!
+ DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
+ DenseMap<GlobalValue::GUID, PrevailingType> GUIDPrevailingResolutions;
+ for (auto &Res : GlobalResolutions) {
+ // Normally resolution have IR name of symbol. We can do nothing here
+ // otherwise. See comments in GlobalResolution struct for more details.
+ if (Res.second.IRName.empty())
+ continue;
+
+ GlobalValue::GUID GUID = GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+
+ if (Res.second.VisibleOutsideSummary && Res.second.Prevailing)
+ GUIDPreservedSymbols.insert(GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName)));
+
+ GUIDPrevailingResolutions[GUID] =
+ Res.second.Prevailing ? PrevailingType::Yes : PrevailingType::No;
+ }
+
+ auto isPrevailing = [&](GlobalValue::GUID G) {
+ auto It = GUIDPrevailingResolutions.find(G);
+ if (It == GUIDPrevailingResolutions.end())
+ return PrevailingType::Unknown;
+ return It->second;
+ };
+ computeDeadSymbolsWithConstProp(ThinLTO.CombinedIndex, GUIDPreservedSymbols,
+ isPrevailing, Conf.OptLevel > 0);
+
+ // Setup output file to emit statistics.
+ std::unique_ptr<ToolOutputFile> StatsFile = nullptr;
+ if (!Conf.StatsFile.empty()) {
+ EnableStatistics(false);
+ std::error_code EC;
+ StatsFile =
+ llvm::make_unique<ToolOutputFile>(Conf.StatsFile, EC, sys::fs::F_None);
+ if (EC)
+ return errorCodeToError(EC);
+ StatsFile->keep();
+ }
+
+ Error Result = runRegularLTONoThread(AddStream);
+ if (!Result)
+ Result = runThinLTO(AddStream, Cache);
+
+ if (StatsFile)
+ PrintStatisticsJSON(StatsFile->os());
+
+ return Result;
+}
+
Error LTO::runRegularLTO(AddStreamFn AddStream) {
for (auto &M : RegularLTO.ModsWithSummaries)
if (Error Err = linkRegularLTO(std::move(M),
@@ -928,6 +980,73 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex);
}
+Error LTO::runRegularLTONoThread(AddStreamFn AddStream) {
+ for (auto &M : RegularLTO.ModsWithSummaries)
+ if (Error Err = linkRegularLTO(std::move(M),
+ /*LivenessFromIndex=*/true))
+ return Err;
+
+ // Make sure commons have the right size/alignment: we kept the largest from
+ // all the prevailing when adding the inputs, and we apply it here.
+ const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
+ for (auto &I : RegularLTO.Commons) {
+ if (!I.second.Prevailing)
+ // Don't do anything if no instance of this common was prevailing.
+ continue;
+ GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first);
+ if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) {
+ // Don't create a new global if the type is already correct, just make
+ // sure the alignment is correct.
+ OldGV->setAlignment(I.second.Align);
+ continue;
+ }
+ ArrayType *Ty =
+ ArrayType::get(Type::getInt8Ty(RegularLTO.Ctx), I.second.Size);
+ auto *GV = new GlobalVariable(*RegularLTO.CombinedModule, Ty, false,
+ GlobalValue::CommonLinkage,
+ ConstantAggregateZero::get(Ty), "");
+ GV->setAlignment(I.second.Align);
+ if (OldGV) {
+ OldGV->replaceAllUsesWith(ConstantExpr::getBitCast(GV, OldGV->getType()));
+ GV->takeName(OldGV);
+ OldGV->eraseFromParent();
+ } else {
+ GV->setName(I.first);
+ }
+ }
+
+ if (Conf.PreOptModuleHook &&
+ !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
+ return Error::success();
+
+ if (!Conf.CodeGenOnly) {
+ for (const auto &R : GlobalResolutions) {
+ if (!R.second.isPrevailingIRSymbol())
+ continue;
+ if (R.second.Partition != 0 &&
+ R.second.Partition != GlobalResolution::External)
+ continue;
+
+ GlobalValue *GV =
+ RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
+ // Ignore symbols defined in other partitions.
+ // Also skip declarations, which are not allowed to have internal linkage.
+ if (!GV || GV->hasLocalLinkage() || GV->isDeclaration())
+ continue;
+ GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
+ : GlobalValue::UnnamedAddr::None);
+ if (EnableLTOInternalization && R.second.Partition == 0)
+ GV->setLinkage(GlobalValue::InternalLinkage);
+ }
+
+ if (Conf.PostInternalizeModuleHook &&
+ !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
+ return Error::success();
+ }
+ return backendNoThread(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
+ std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex);
+}
+
/// This class defines the interface to the ThinLTO backend.
class lto::ThinBackendProc {
protected:
@@ -952,8 +1071,9 @@ public:
};
namespace {
+template<class ThreadEngine>
class InProcessThinBackend : public ThinBackendProc {
- ThreadPool BackendThreadPool;
+ ThreadEngine BackendThreadPool;
AddStreamFn AddStream;
NativeObjectCache Cache;
std::set<GlobalValue::GUID> CfiFunctionDefs;
@@ -1065,9 +1185,19 @@ ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) {
return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, NativeObjectCache Cache) {
- return llvm::make_unique<InProcessThinBackend>(
+ return llvm::make_unique<InProcessThinBackend<ThreadPool>>(
+ Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
+ AddStream, Cache);
+ };
+}
+ThinBackend lto::createInProcessThinBackendNoThread(unsigned ParallelismLevel) {
+ return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
+ const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
+ AddStreamFn AddStream, NativeObjectCache Cache) {
+ ThinBackendProc* Backend = new InProcessThinBackend<SequentialThreadPool>(
Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
AddStream, Cache);
+ return std::unique_ptr<ThinBackendProc>(Backend);
};
}
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 926c419e34a..2c263ed86a9 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -333,10 +333,11 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
DwoOut->keep();
}
-void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
+template<class ThreadPoolEngine>
+static void splitCodeGen_(Config &C, TargetMachine *TM, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel,
std::unique_ptr<Module> Mod) {
- ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
+ ThreadPoolEngine CodegenThreadPool(ParallelCodeGenParallelismLevel);
unsigned ThreadCount = 0;
const Target *T = &TM->getTarget();
@@ -380,6 +381,17 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
// can leave the function scope.
CodegenThreadPool.wait();
}
+void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
+ unsigned ParallelCodeGenParallelismLevel,
+ std::unique_ptr<Module> Mod) {
+ splitCodeGen_<ThreadPool>(C, TM, AddStream, ParallelCodeGenParallelismLevel, std::move(Mod));
+}
+
+void splitCodeGenNoThread(Config &C, TargetMachine *TM, AddStreamFn AddStream,
+ unsigned ParallelCodeGenParallelismLevel,
+ std::unique_ptr<Module> Mod) {
+ splitCodeGen_<SequentialThreadPool>(C, TM, AddStream, ParallelCodeGenParallelismLevel, std::move(Mod));
+}
Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
if (!C.OverrideTriple.empty())
@@ -439,6 +451,38 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
}
+Error lto::backendNoThread(Config &C, AddStreamFn AddStream,
+ unsigned ParallelCodeGenParallelismLevel,
+ std::unique_ptr<Module> Mod,
+ ModuleSummaryIndex &CombinedIndex) {
+ Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
+ if (!TOrErr)
+ return TOrErr.takeError();
+
+ std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
+
+ // Setup optimization remarks.
+ auto DiagFileOrErr = lto::setupOptimizationRemarks(
+ Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness);
+ if (!DiagFileOrErr)
+ return DiagFileOrErr.takeError();
+ auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
+
+ if (!C.CodeGenOnly) {
+ if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
+ /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
+ }
+
+ if (ParallelCodeGenParallelismLevel == 1) {
+ codegen(C, TM.get(), AddStream, 0, *Mod);
+ } else {
+ splitCodeGenNoThread(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
+ std::move(Mod));
+ }
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
+}
+
static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
const ModuleSummaryIndex &Index) {
std::vector<GlobalValue*> DeadGVs;
diff --git a/llvm/lib/Support/ThreadPool.cpp b/llvm/lib/Support/ThreadPool.cpp
index d0212ca1346..3d760edbcb7 100644
--- a/llvm/lib/Support/ThreadPool.cpp
+++ b/llvm/lib/Support/ThreadPool.cpp
@@ -19,8 +19,6 @@
using namespace llvm;
-#if LLVM_ENABLE_THREADS
-
// Default to hardware_concurrency
ThreadPool::ThreadPool() : ThreadPool(hardware_concurrency()) {}
@@ -107,7 +105,7 @@ ThreadPool::~ThreadPool() {
Worker.join();
}
-#else // LLVM_ENABLE_THREADS Disabled
+#define ThreadPool SequentialThreadPool
ThreadPool::ThreadPool() : ThreadPool(0) {}
@@ -142,5 +140,3 @@ std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
ThreadPool::~ThreadPool() {
wait();
}
-
-#endif
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 738cafa6cac..8ef75d2589c 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -848,7 +848,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
Conf.DisableVerify = options::DisableVerify;
Conf.OptLevel = options::OptLevel;
if (options::Parallelism)
- Backend = createInProcessThinBackend(options::Parallelism);
+ Backend = createInProcessThinBackendNoThread(options::Parallelism);
if (options::thinlto_index_only) {
std::string OldPrefix, NewPrefix;
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
@@ -856,6 +856,9 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
options::thinlto_emit_imports_files,
LinkedObjectsFile, OnIndexWrite);
}
+ if(!Backend)
+ Backend = createInProcessThinBackendNoThread(llvm::heavyweight_hardware_concurrency());
+
Conf.OverrideTriple = options::triple;
Conf.DefaultTriple = sys::getDefaultTargetTriple();
@@ -1039,7 +1042,7 @@ static std::vector<std::pair<SmallString<128>, bool>> runLTO() {
if (!options::cache_dir.empty())
Cache = check(localCache(options::cache_dir, AddBuffer));
- check(Lto->run(AddStream, Cache));
+ check(Lto->runNoThread(AddStream, Cache));
// Write empty output files that may be expected by the distributed build
// system.
--
2.20.1