[PATCH] D44716: [lld] fix data race in ICF.cpp

Bob Haarman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 20 16:07:55 PDT 2018


inglorion created this revision.
inglorion added reviewers: ruiu, pcc, rnk.
inglorion added a comment.

ruiu informs me similar code exists in the other ports. Let's get this reviewed first and then I'll update the others.


Fixes PR36823.


https://reviews.llvm.org/D44716

Files:
  lld/COFF/ICF.cpp


Index: lld/COFF/ICF.cpp
===================================================================
--- lld/COFF/ICF.cpp
+++ lld/COFF/ICF.cpp
@@ -168,6 +168,7 @@
   return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
 }
 
+// Find the first Chunk after Begin that has a different class from Begin.
 size_t ICF::findBoundary(size_t Begin, size_t End) {
   for (size_t I = Begin + 1; I < End; ++I)
     if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2])
@@ -177,11 +178,8 @@
 
 void ICF::forEachClassRange(size_t Begin, size_t End,
                             std::function<void(size_t, size_t)> Fn) {
-  if (Begin > 0)
-    Begin = findBoundary(Begin - 1, End);
-
   while (Begin < End) {
-    size_t Mid = findBoundary(Begin, Chunks.size());
+    size_t Mid = findBoundary(Begin, End);
     Fn(Begin, Mid);
     Begin = Mid;
   }
@@ -197,12 +195,22 @@
     return;
   }
 
-  // Split sections into 256 shards and call Fn in parallel.
-  size_t NumShards = 256;
+  // Shard into non-overlapping intervals, and call Fn in parallel.
+  // The sharding must be completed before any calls to Fn are made
+  // so that Fn can modify the Chunks in its shard without causing data
+  // races.
+  const size_t NumShards = 256;
+  size_t Boundaries[NumShards];
   size_t Step = Chunks.size() / NumShards;
   for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
-    size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
-    forEachClassRange(I * Step, End, Fn);
+    size_t Begin = I == 0 ? 0 : findBoundary(I * Step - 1, Chunks.size());
+    Boundaries[I] = findBoundary(Begin, Chunks.size());
+  });
+  for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
+    if (I == 0)
+      forEachClassRange(0, Boundaries[I], Fn);
+    else if (Boundaries[I] > Boundaries[I - 1])
+      forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
   });
   ++Cnt;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D44716.139218.patch
Type: text/x-patch
Size: 1915 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180320/d9faa4e4/attachment.bin>


More information about the llvm-commits mailing list