[llvm] [LLD] Avoid non-deterministic relocations processing. (PR #107186)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 3 23:01:07 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Alexey Lapshin (avl-llvm)

<details>
<summary>Changes</summary>

TaskGroup has a "sequential" mode for deterministic processing. LLD uses this for relocations handling. But, As it places relocations to different vectors(based on getThreadIndex), the actual locations can be non-deterministic:

    if (shard)
      part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
          {&isec, isec.relocs().size() - 1});

It is neccessary to use the same thread index to have the same locations. This patch changes "sequential" mode to always execute tasks on single thread with index 0.

Fixes this https://github.com/llvm/llvm-project/issues/105958.

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


3 Files Affected:

- (modified) llvm/include/llvm/Support/Parallel.h (+2-3) 
- (modified) llvm/lib/Support/Parallel.cpp (+2-11) 
- (modified) llvm/unittests/Support/ParallelTest.cpp (+6-1) 


``````````diff
diff --git a/llvm/include/llvm/Support/Parallel.h b/llvm/include/llvm/Support/Parallel.h
index 8170da98f15a8c..0e1f4fadcf4fe6 100644
--- a/llvm/include/llvm/Support/Parallel.h
+++ b/llvm/include/llvm/Support/Parallel.h
@@ -96,9 +96,8 @@ class TaskGroup {
 
   // Spawn a task, but does not wait for it to finish.
   // Tasks marked with \p Sequential will be executed
-  // exactly in the order which they were spawned.
-  // Note: Sequential tasks may be executed on different
-  // threads, but strictly in sequential order.
+  // exactly in the order which they were spawned and
+  // on the thread with index 0.
   void spawn(std::function<void()> f, bool Sequential = false);
 
   void sync() const { L.sync(); }
diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp
index a3ef3d9c621b98..3ef3b65153937a 100644
--- a/llvm/lib/Support/Parallel.cpp
+++ b/llvm/lib/Support/Parallel.cpp
@@ -113,7 +113,7 @@ class ThreadPoolExecutor : public Executor {
 
 private:
   bool hasSequentialTasks() const {
-    return !WorkQueueSequential.empty() && !SequentialQueueIsLocked;
+    return !WorkQueueSequential.empty() && (getThreadIndex() == 0);
   }
 
   bool hasGeneralTasks() const { return !WorkQueue.empty(); }
@@ -128,24 +128,15 @@ class ThreadPoolExecutor : public Executor {
       });
       if (Stop)
         break;
-      bool Sequential = hasSequentialTasks();
-      if (Sequential)
-        SequentialQueueIsLocked = true;
-      else
-        assert(hasGeneralTasks());
-
-      auto &Queue = Sequential ? WorkQueueSequential : WorkQueue;
+      auto &Queue = hasSequentialTasks() ? WorkQueueSequential : WorkQueue;
       auto Task = std::move(Queue.back());
       Queue.pop_back();
       Lock.unlock();
       Task();
-      if (Sequential)
-        SequentialQueueIsLocked = false;
     }
   }
 
   std::atomic<bool> Stop{false};
-  std::atomic<bool> SequentialQueueIsLocked{false};
   std::deque<std::function<void()>> WorkQueue;
   std::deque<std::function<void()>> WorkQueueSequential;
   std::mutex Mutex;
diff --git a/llvm/unittests/Support/ParallelTest.cpp b/llvm/unittests/Support/ParallelTest.cpp
index 0eafb9b401bee7..c6acd302945651 100644
--- a/llvm/unittests/Support/ParallelTest.cpp
+++ b/llvm/unittests/Support/ParallelTest.cpp
@@ -99,7 +99,12 @@ TEST(Parallel, TaskGroupSequentialFor) {
   {
     parallel::TaskGroup tg;
     for (size_t Idx = 0; Idx < 500; Idx++)
-      tg.spawn([&Count, Idx]() { EXPECT_EQ(Count++, Idx); }, true);
+      tg.spawn(
+          [&Count, Idx]() {
+            EXPECT_EQ(Count++, Idx);
+            EXPECT_EQ(llvm::parallel::getThreadIndex(), 0u);
+          },
+          true);
   }
   EXPECT_EQ(Count, 500ul);
 }

``````````

</details>


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


More information about the llvm-commits mailing list