Blob Blame History Raw
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