[llvm] [ORC] Fix race when checking isComplete (PR #165063)

Jordan Rupprecht via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 24 18:50:24 PDT 2025


https://github.com/rupprecht created https://github.com/llvm/llvm-project/pull/165063

After #164340 there is a tsan race on `OutstandingSymbolsCount` when decrementing it in `notifySymbolMetRequiredState` vs reading it in `isComplete()`. Fix this by having `IL_emit` filter out non-completed queries when it has the lock to do so, and that way we avoid needing to call `isComplete()` later.

>From b4c18337807ba1e7f88fb8f9151330ad42a5bdd3 Mon Sep 17 00:00:00 2001
From: Jordan Rupprecht <rupprecht at google.com>
Date: Fri, 24 Oct 2025 18:43:50 -0700
Subject: [PATCH] [ORC] Fix race when checking isComplete

---
 llvm/include/llvm/ExecutionEngine/Orc/Core.h | 2 +-
 llvm/lib/ExecutionEngine/Orc/Core.cpp        | 9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index f05febfcc96b4..24a0cb74b1fbc 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -1768,7 +1768,7 @@ class ExecutionSession {
   // FIXME: We should be able to derive FailedSymsForQuery from each query once
   //        we fix how the detach operation works.
   struct EmitQueries {
-    JITDylib::AsynchronousSymbolQuerySet Updated;
+    JITDylib::AsynchronousSymbolQuerySet Completed;
     JITDylib::AsynchronousSymbolQuerySet Failed;
     DenseMap<AsynchronousSymbolQuery *, std::shared_ptr<SymbolDependenceMap>>
         FailedSymsForQuery;
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index 8d413a35f5a93..5b6f6229b9fcc 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -2901,13 +2901,15 @@ ExecutionSession::IL_emit(MaterializationResponsibility &MR,
 
   for (auto &SN : ER.Ready)
     IL_collectQueries(
-        EQ.Updated, SN->defs(),
+        EQ.Completed, SN->defs(),
         [](JITDylib::SymbolTableEntry &E) { E.setState(SymbolState::Ready); },
         [](AsynchronousSymbolQuery &Q, JITDylib &JD,
            NonOwningSymbolStringPtr Name, JITDylib::SymbolTableEntry &E) {
           Q.notifySymbolMetRequiredState(SymbolStringPtr(Name), E.getSymbol());
         });
 
+  std::erase_if(EQ.Completed, [](const auto &Q) { return !Q->isComplete(); });
+
 #ifdef EXPENSIVE_CHECKS
   verifySessionState("exiting ExecutionSession::IL_emit");
 #endif
@@ -3043,9 +3045,8 @@ Error ExecutionSession::OL_notifyEmitted(
     }
   }
 
-  for (auto &UQ : EmitQueries->Updated)
-    if (UQ->isComplete())
-      UQ->handleComplete(*this);
+  for (auto &UQ : EmitQueries->Completed)
+    UQ->handleComplete(*this);
 
   // If there are any bad dependencies then return an error.
   if (!BadDeps.empty()) {



More information about the llvm-commits mailing list