[llvm-branch-commits] [lld] [llvm] release/23.x: [CMake] Added missing LLVM_PTHREAD_LIB dependency. (#211041) (PR #211206)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jul 22 02:03:05 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-platform-windows

@llvm/pr-subscribers-lld

Author: llvmbot

<details>
<summary>Changes</summary>

Backport 914d5a1 4f5675a

Requested by: @<!-- -->bd1976bris

---
Full diff: https://github.com/llvm/llvm-project/pull/211206.diff


14 Files Affected:

- (modified) lld/COFF/Driver.cpp (+3) 
- (modified) lld/COFF/LTO.cpp (+5) 
- (modified) lld/COFF/LTO.h (+1) 
- (modified) lld/COFF/SymbolTable.cpp (+5) 
- (modified) lld/COFF/SymbolTable.h (+2) 
- (modified) lld/ELF/Config.h (+1) 
- (modified) lld/ELF/Driver.cpp (+9) 
- (modified) lld/ELF/LTO.cpp (+5) 
- (modified) lld/ELF/LTO.h (+1) 
- (modified) llvm/include/llvm/DTLTO/DTLTO.h (+23-1) 
- (modified) llvm/include/llvm/LTO/LTO.h (+8) 
- (modified) llvm/lib/DTLTO/CMakeLists.txt (+3) 
- (modified) llvm/lib/DTLTO/DTLTO.cpp (+48-16) 
- (modified) llvm/tools/llvm-lto2/llvm-lto2.cpp (+1) 


``````````diff
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index dc4903a5fe126..2d70193187ef1 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2960,6 +2960,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   // Write the result.
   writeResult(ctx);
+  // LTO cleanup may create time trace events. Wait for it to complete before
+  // writing the time trace data.
+  ctx.forEachSymtab([](SymbolTable &symtab) { symtab.waitForLTOCleanup(); });
 
   // Stop early so we can print the results.
   rootTimer.stop();
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index 0329f6c2e9cea..71413b0315c08 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -156,6 +156,11 @@ BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {
 
 BitcodeCompiler::~BitcodeCompiler() = default;
 
+void BitcodeCompiler::waitForLTOCleanup() {
+  if (ltoObj)
+    ltoObj->waitForCleanup();
+}
+
 static void undefine(Symbol *s) { replaceSymbol<Undefined>(s, s->getName()); }
 
 void BitcodeCompiler::add(BitcodeFile &f) {
diff --git a/lld/COFF/LTO.h b/lld/COFF/LTO.h
index 73e855e567b09..f097d53b9a15f 100644
--- a/lld/COFF/LTO.h
+++ b/lld/COFF/LTO.h
@@ -46,6 +46,7 @@ class BitcodeCompiler {
   void add(BitcodeFile &f);
   std::vector<InputFile *> compile();
   void setBitcodeLibFuncs(ArrayRef<StringRef> bitcodeLibFuncs);
+  void waitForLTOCleanup();
 
 private:
   std::unique_ptr<llvm::lto::LTO> ltoObj;
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index df540be800e41..ea5bdbc0be489 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -1511,4 +1511,9 @@ void SymbolTable::compileBitcodeFiles() {
   }
 }
 
+void SymbolTable::waitForLTOCleanup() {
+  if (lto)
+    lto->waitForLTOCleanup();
+}
+
 } // namespace lld::coff
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index aadd366c7d39f..12d2e8cb23f8e 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -109,6 +109,8 @@ class SymbolTable {
   // added and before the writer writes results to a file.
   void compileBitcodeFiles();
 
+  void waitForLTOCleanup();
+
   // Creates an Undefined symbol and marks it as live.
   Symbol *addGCRoot(StringRef sym, bool aliasEC = false);
 
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 863f3223094bb..1426aab12758f 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -215,6 +215,7 @@ class LinkerDriver {
   void createFiles(llvm::opt::InputArgList &args);
   void loadFiles();
   void inferMachineType();
+  void waitForLTOCleanup();
   template <class ELFT> void link(llvm::opt::InputArgList &args);
   template <class ELFT> void compileBitcodeFiles(bool skipLinkedOutput);
   // True if we are in --whole-archive and --no-whole-archive.
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 77821e8c813ef..51d9e32419f9f 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -625,6 +625,11 @@ constexpr const char *saveTempsValues[] = {
 
 LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}
 
+void LinkerDriver::waitForLTOCleanup() {
+  if (lto)
+    lto->waitForLTOCleanup();
+}
+
 void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   ELFOptTable parser;
   opt::InputArgList args = parser.parse(ctx, argsArr.slice(1));
@@ -707,6 +712,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     invokeELFT(link, args);
   }
 
+  // LTO cleanup may create time trace events. Wait for it to complete before
+  // writing the time trace data.
+  waitForLTOCleanup();
+
   if (ctx.arg.timeTraceEnabled) {
     checkError(ctx.e, timeTraceProfilerWrite(
                           args.getLastArgValue(OPT_time_trace_eq).str(),
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index e40575bffec62..a11681133373d 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -231,6 +231,11 @@ BitcodeCompiler::BitcodeCompiler(Ctx &ctx) : ctx(ctx) {
 
 BitcodeCompiler::~BitcodeCompiler() = default;
 
+void BitcodeCompiler::waitForLTOCleanup() {
+  if (ltoObj)
+    ltoObj->waitForCleanup();
+}
+
 void BitcodeCompiler::add(BitcodeFile &f) {
   lto::InputFile &obj = *f.obj;
   bool isExec = !ctx.arg.shared && !ctx.arg.relocatable;
diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h
index c8cb2156d90ca..fdbeb32030eac 100644
--- a/lld/ELF/LTO.h
+++ b/lld/ELF/LTO.h
@@ -44,6 +44,7 @@ class BitcodeCompiler {
   void add(BitcodeFile &f);
   SmallVector<std::unique_ptr<InputFile>, 0> compile();
   void setBitcodeLibFuncs(ArrayRef<StringRef> bitcodeLibFuncs);
+  void waitForLTOCleanup();
 
 private:
   Ctx &ctx;
diff --git a/llvm/include/llvm/DTLTO/DTLTO.h b/llvm/include/llvm/DTLTO/DTLTO.h
index 2d532bc384685..13b83ec6e0770 100644
--- a/llvm/include/llvm/DTLTO/DTLTO.h
+++ b/llvm/include/llvm/DTLTO/DTLTO.h
@@ -19,10 +19,12 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/LTO/LTO.h"
-#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/ThreadPool.h"
 
 #include <functional>
+#include <string>
+#include <utility>
 #include <vector>
 
 namespace llvm {
@@ -94,6 +96,12 @@ class LLVM_ABI DTLTO : public LTO {
   /// Cache) for each task identifier.
   virtual Error run(AddStreamFn AddStream, FileCache Cache = {}) override;
 
+  /// Wait for LTO cleanup. Clients may call this after run() once subsequent
+  /// linking work that can overlap with cleanup is complete. Cleanup may emit
+  /// time trace events, so this must be called before time trace data is
+  /// finalized.
+  void waitForCleanup() override;
+
 private:
   /// DTLTO archive support.
   ///
@@ -356,6 +364,20 @@ class LLVM_ABI DTLTO : public LTO {
   // Cleanup files list.
   std::vector<std::string> CleanupList;
 
+  // There can be many temporary files to remove. Performing deletion in the
+  // background can save a few seconds on Windows hosts.
+  struct BackgroundDeletion : DefaultThreadPool {
+    BackgroundDeletion();
+    ~BackgroundDeletion();
+
+    void removeFiles(std::vector<std::string> &&Files, const Config &Conf);
+    void waitForTasks();
+
+    std::vector<std::string> Warnings;
+  };
+
+  BackgroundDeletion BackgroundDeleter;
+
   // Record a file for cleanup and register signal-time removal if requested.
   void addToCleanup(StringRef Filename) {
     CleanupList.push_back(Filename.str());
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 32aa671183890..cea66f99b99bb 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -439,6 +439,14 @@ class LLVM_ABI LTO {
   /// Cache) for each task identifier.
   virtual Error run(AddStreamFn AddStream, FileCache Cache = {});
 
+  /// Wait for cleanup work started by run() to finish.
+  ///
+  /// A client may delay this call to overlap asynchronous cleanup with later
+  /// linking work, but must call it before finalizing time trace data because
+  /// cleanup may emit time trace events. Most LTO implementations have no
+  /// asynchronous cleanup.
+  virtual void waitForCleanup() {}
+
   /// Static method that returns a list of libcall symbols that can be generated
   /// by LTO but might not be visible from bitcode symbol table.
   static SmallVector<const char *> getRuntimeLibcallSymbols(const Triple &TT);
diff --git a/llvm/lib/DTLTO/CMakeLists.txt b/llvm/lib/DTLTO/CMakeLists.txt
index 09c8c20b6a475..f40f570932108 100644
--- a/llvm/lib/DTLTO/CMakeLists.txt
+++ b/llvm/lib/DTLTO/CMakeLists.txt
@@ -3,6 +3,9 @@ add_llvm_component_library(LLVMDTLTO
   DTLTO.cpp
   DTLTODistributionDriver.cpp
 
+  LINK_LIBS
+  ${LLVM_PTHREAD_LIB}
+
   LINK_COMPONENTS
   BinaryFormat
   Core
diff --git a/llvm/lib/DTLTO/DTLTO.cpp b/llvm/lib/DTLTO/DTLTO.cpp
index bca05fa53e889..1d42d09d0820a 100644
--- a/llvm/lib/DTLTO/DTLTO.cpp
+++ b/llvm/lib/DTLTO/DTLTO.cpp
@@ -27,27 +27,59 @@
 #include "llvm/Support/raw_ostream.h"
 
 #include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
 
 using namespace llvm;
 
+// Experimentation showed that serial deletion is most efficient, hence
+// a single thread.
+lto::DTLTO::BackgroundDeletion::BackgroundDeletion()
+    : DefaultThreadPool(hardware_concurrency(1)) {}
+
+lto::DTLTO::BackgroundDeletion::~BackgroundDeletion() { waitForTasks(); }
+
+void lto::DTLTO::BackgroundDeletion::waitForTasks() {
+  wait();
+  for (const std::string &Warning : Warnings)
+    errs() << "warning: could not remove the file " << Warning << "\n";
+  Warnings.clear();
+}
+
+void lto::DTLTO::BackgroundDeletion::removeFiles(
+    std::vector<std::string> &&Files, const Config &Conf) {
+  if (Files.empty())
+    return;
+
+  async([this, Files = std::move(Files), TTE = Conf.TimeTraceEnabled,
+         TTG = Conf.TimeTraceGranularity] {
+    if (LLVM_ENABLE_THREADS && TTE)
+      timeTraceProfilerInitialize(TTG, "Remove DTLTO temporary files");
+    {
+      TimeTraceScope TimeScope("Remove DTLTO temporary files");
+      for (const std::string &Path : Files) {
+        std::error_code EC = sys::fs::remove(Path, true);
+        if (!EC ||
+            EC == std::make_error_code(std::errc::no_such_file_or_directory))
+          continue;
+
+        Warnings.emplace_back("'" + Path + "': " + EC.message());
+      }
+    }
+    if (LLVM_ENABLE_THREADS && TTE)
+      timeTraceProfilerFinishThread();
+  });
+}
+
+void lto::DTLTO::waitForCleanup() { BackgroundDeleter.waitForTasks(); }
+
 // Remove temporary files created to enable distribution.
 void lto::DTLTO::cleanup() {
-  if (!SaveTemps) {
-    // Remove one file, report error if any.
-    auto removeFile = [](StringRef FileName) -> void {
-      std::error_code EC = sys::fs::remove(FileName, true);
-      if (EC &&
-          EC != std::make_error_code(std::errc::no_such_file_or_directory))
-        errs() << "warning: could not remove the file '" << FileName
-               << "': " << EC.message() << "\n";
-    };
-
-    TimeTraceScope JobScope("Remove DTLTO temporary files");
-    for (const auto &Name : CleanupList)
-      removeFile(Name);
-    // Clean the CleanupList for safety.
-    CleanupList.clear();
-  }
+  if (SaveTemps)
+    return;
+
+  BackgroundDeleter.removeFiles(std::move(CleanupList), Conf);
 }
 
 // Runs the DTLTO thin link phase, producing per-module summary indices,
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 4bcf04df89ac9..7dd7d9ea67150 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -541,6 +541,7 @@ static int run(int argc, char **argv) {
                   "failed to create cache");
 
   check(Lto->run(AddStream, Cache), "LTO::run failed");
+  Lto->waitForCleanup();
   return static_cast<int>(HasErrors);
 }
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/211206


More information about the llvm-branch-commits mailing list