Index: lld/COFF/ICF.cpp =================================================================== --- lld/COFF/ICF.cpp +++ lld/COFF/ICF.cpp @@ -21,9 +21,9 @@ #include "Chunks.h" #include "Error.h" #include "Symbols.h" -#include "lld/Core/Parallel.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Parallel.h" #include "llvm/Support/raw_ostream.h" #include #include Index: lld/COFF/MapFile.cpp =================================================================== --- lld/COFF/MapFile.cpp +++ lld/COFF/MapFile.cpp @@ -25,7 +25,7 @@ #include "Symbols.h" #include "Writer.h" -#include "lld/Core/Parallel.h" +#include "llvm/Support/Parallel.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -76,7 +76,7 @@ static DenseMap getSymbolStrings(ArrayRef Syms) { std::vector Str(Syms.size()); - for_each_n(parallel::par, (size_t)0, Syms.size(), [&](size_t I) { + for_each_n(llvm::parallel::par, (size_t)0, Syms.size(), [&](size_t I) { raw_string_ostream OS(Str[I]); writeHeader(OS, Syms[I]->getRVA(), 0, 0); OS << indent(2) << toString(*Syms[I]); Index: lld/COFF/Writer.cpp =================================================================== --- lld/COFF/Writer.cpp +++ lld/COFF/Writer.cpp @@ -17,13 +17,13 @@ #include "PDB.h" #include "SymbolTable.h" #include "Symbols.h" -#include "lld/Core/Parallel.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/Parallel.h" #include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/raw_ostream.h" #include @@ -745,8 +745,8 @@ // ADD instructions). if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE) memset(SecBuf, 0xCC, Sec->getRawSize()); - for_each(parallel::par, Sec->getChunks().begin(), Sec->getChunks().end(), - [&](Chunk *C) { C->writeTo(SecBuf); }); + for_each(llvm::parallel::par, Sec->getChunks().begin(), + Sec->getChunks().end(), [&](Chunk *C) { C->writeTo(SecBuf); }); } } @@ -760,13 +760,13 @@ uint8_t *End = Begin + Sec->getVirtualSize(); if (Config->Machine == AMD64) { struct Entry { ulittle32_t Begin, End, Unwind; }; - sort(parallel::par, (Entry *)Begin, (Entry *)End, + sort(llvm::parallel::par, (Entry *)Begin, (Entry *)End, [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); return; } if (Config->Machine == ARMNT) { struct Entry { ulittle32_t Begin, Unwind; }; - sort(parallel::par, (Entry *)Begin, (Entry *)End, + sort(llvm::parallel::par, (Entry *)Begin, (Entry *)End, [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); return; } Index: lld/ELF/Threads.h =================================================================== --- lld/ELF/Threads.h +++ lld/ELF/Threads.h @@ -61,7 +61,7 @@ #include "Config.h" -#include "lld/Core/Parallel.h" +#include "llvm/Support/Parallel.h" #include #include @@ -71,17 +71,17 @@ template void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) { if (Config->Threads) - for_each(parallel::par, Begin, End, Fn); + for_each(llvm::parallel::par, Begin, End, Fn); else - for_each(parallel::seq, Begin, End, Fn); + for_each(llvm::parallel::seq, Begin, End, Fn); } inline void parallelFor(size_t Begin, size_t End, std::function Fn) { if (Config->Threads) - for_each_n(parallel::par, Begin, End, Fn); + for_each_n(llvm::parallel::par, Begin, End, Fn); else - for_each_n(parallel::seq, Begin, End, Fn); + for_each_n(llvm::parallel::seq, Begin, End, Fn); } } } Index: lld/include/lld/Core/TaskGroup.h =================================================================== --- lld/include/lld/Core/TaskGroup.h +++ /dev/null @@ -1,65 +0,0 @@ -//===- lld/Core/TaskGroup.h - Task Group ----------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_TASKGROUP_H -#define LLD_CORE_TASKGROUP_H - -#include "lld/Core/LLVM.h" - -#include -#include -#include - -namespace lld { -/// \brief Allows one or more threads to wait on a potentially unknown number of -/// events. -/// -/// A latch starts at \p count. inc() increments this, and dec() decrements it. -/// All calls to sync() will block while the count is not 0. -/// -/// Calling dec() on a Latch with a count of 0 has undefined behaivor. -class Latch { - uint32_t _count; - mutable std::mutex _condMut; - mutable std::condition_variable _cond; - -public: - explicit Latch(uint32_t count = 0) : _count(count) {} - ~Latch() { sync(); } - - void inc() { - std::unique_lock lock(_condMut); - ++_count; - } - - void dec() { - std::unique_lock lock(_condMut); - if (--_count == 0) - _cond.notify_all(); - } - - void sync() const { - std::unique_lock lock(_condMut); - _cond.wait(lock, [&] { return _count == 0; }); - } -}; - -/// \brief Allows launching a number of tasks and waiting for them to finish -/// either explicitly via sync() or implicitly on destruction. -class TaskGroup { - Latch _latch; - -public: - void spawn(std::function f); - - void sync() const { _latch.sync(); } -}; -} - -#endif Index: lld/lib/Core/CMakeLists.txt =================================================================== --- lld/lib/Core/CMakeLists.txt +++ lld/lib/Core/CMakeLists.txt @@ -12,7 +12,6 @@ Resolver.cpp SymbolTable.cpp TargetOptionsCommandFlags.cpp - TaskGroup.cpp Writer.cpp ADDITIONAL_HEADER_DIRS Index: lld/lib/ReaderWriter/MachO/LayoutPass.cpp =================================================================== --- lld/lib/ReaderWriter/MachO/LayoutPass.cpp +++ lld/lib/ReaderWriter/MachO/LayoutPass.cpp @@ -9,12 +9,12 @@ #include "LayoutPass.h" #include "lld/Core/Instrumentation.h" -#include "lld/Core/Parallel.h" #include "lld/Core/PassManager.h" #include "lld/ReaderWriter/MachOLinkingContext.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Parallel.h" #include #include #include @@ -461,7 +461,7 @@ }); std::vector vec = decorate(atomRange); - sort(parallel::par, vec.begin(), vec.end(), + sort(llvm::parallel::par, vec.begin(), vec.end(), [&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool { return compareAtoms(l, r, _customSorter); }); Index: lld/unittests/CMakeLists.txt =================================================================== --- lld/unittests/CMakeLists.txt +++ lld/unittests/CMakeLists.txt @@ -12,6 +12,5 @@ target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS}) endfunction() -add_subdirectory(CoreTests) add_subdirectory(DriverTests) add_subdirectory(MachOTests) Index: lld/unittests/CoreTests/CMakeLists.txt =================================================================== --- lld/unittests/CoreTests/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_lld_unittest(CoreTests - ParallelTest.cpp - ) - -target_link_libraries(CoreTests - lldCore ${LLVM_PTHREAD_LIB} - ) Index: llvm/include/llvm/Support/Parallel.h =================================================================== --- llvm/include/llvm/Support/Parallel.h +++ llvm/include/llvm/Support/Parallel.h @@ -1,29 +1,71 @@ -//===- lld/Core/Parallel.h - Parallel utilities ---------------------------===// +//===- llvm/Support/Parallel.h - Parallel algorithms ----------------------===// // -// The LLVM Linker +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef LLD_CORE_PARALLEL_H -#define LLD_CORE_PARALLEL_H +#ifndef LLVM_SUPPORT_PARALLEL_H +#define LLVM_SUPPORT_PARALLEL_H -#include "lld/Core/LLVM.h" -#include "lld/Core/TaskGroup.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/TaskGroup.h" #include +#include +#include +#include #if defined(_MSC_VER) && LLVM_ENABLE_THREADS +#pragma warning(push) +#pragma warning(disable : 4530) #include #include +#pragma warning(pop) #endif -namespace lld { +namespace llvm { + +namespace detail { +class Latch { + uint32_t Count; + mutable std::mutex Mutex; + mutable std::condition_variable Cond; + +public: + explicit Latch(uint32_t count = 0) : Count(Count) {} + ~Latch() { sync(); } + + void inc() { + std::unique_lock lock(Mutex); + ++Count; + } + + void dec() { + std::unique_lock lock(Mutex); + if (--Count == 0) + Cond.notify_all(); + } + + void sync() const { + std::unique_lock lock(Mutex); + Cond.wait(lock, [&] { return Count == 0; }); + } +}; + +class TaskGroup { + Latch L; + +public: + void spawn(std::function f); + + void sync() const { L.sync(); } +}; +} namespace parallel { struct sequential_execution_policy {}; @@ -204,6 +246,6 @@ #endif } // namespace parallel -} // End namespace lld +} // namespace llvm -#endif // LLD_CORE_PARALLEL_H +#endif // LLVM_SUPPORT_PARALLEL_H Index: llvm/lib/Support/CMakeLists.txt =================================================================== --- llvm/lib/Support/CMakeLists.txt +++ llvm/lib/Support/CMakeLists.txt @@ -81,6 +81,7 @@ MD5.cpp NativeFormatting.cpp Options.cpp + Parallel.cpp PluginLoader.cpp PrettyStackTrace.cpp RandomNumberGenerator.cpp Index: llvm/lib/Support/Parallel.cpp =================================================================== --- llvm/lib/Support/Parallel.cpp +++ llvm/lib/Support/Parallel.cpp @@ -1,25 +1,20 @@ -//===- lld/Core/TaskGroup.cpp - Task Group --------------------------------===// +//===- llvm/Support/Parallel.cpp - Parallel algorithms --------------------===// // -// The LLVM Linker +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include "lld/Core/TaskGroup.h" +#include "llvm/Support/Parallel.h" #include "llvm/Config/llvm-config.h" #include #include #include -#if defined(_MSC_VER) && LLVM_ENABLE_THREADS -#include -#include -#endif - -using namespace lld; +using namespace llvm; namespace { @@ -132,10 +127,10 @@ #endif } -void TaskGroup::spawn(std::function f) { - _latch.inc(); +void detail::TaskGroup::spawn(std::function f) { + L.inc(); Executor::getDefaultExecutor()->add([&, f] { f(); - _latch.dec(); + L.dec(); }); } Index: llvm/unittests/Support/CMakeLists.txt =================================================================== --- llvm/unittests/Support/CMakeLists.txt +++ llvm/unittests/Support/CMakeLists.txt @@ -36,6 +36,7 @@ MemoryBufferTest.cpp MemoryTest.cpp NativeFormatTests.cpp + ParallelTest.cpp Path.cpp ProcessTest.cpp ProgramTest.cpp Index: llvm/unittests/Support/ParallelTest.cpp =================================================================== --- llvm/unittests/Support/ParallelTest.cpp +++ llvm/unittests/Support/ParallelTest.cpp @@ -1,4 +1,4 @@ -//===- lld/unittest/ParallelTest.cpp --------------------------------------===// +//===- llvm/unittest/Support/ParallelTest.cpp -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -12,13 +12,15 @@ /// //===----------------------------------------------------------------------===// +#include "llvm/Support/Parallel.h" #include "gtest/gtest.h" -#include "lld/Core/Parallel.h" #include #include uint32_t array[1024 * 1024]; +using namespace llvm; + TEST(Parallel, sort) { std::mt19937 randEngine; std::uniform_int_distribution dist; @@ -26,7 +28,7 @@ for (auto &i : array) i = dist(randEngine); - sort(lld::parallel::par, std::begin(array), std::end(array)); + sort(parallel::par, std::begin(array), std::end(array)); ASSERT_TRUE(std::is_sorted(std::begin(array), std::end(array))); } @@ -36,7 +38,7 @@ // writing. uint32_t range[2050]; std::fill(range, range + 2050, 1); - for_each_n(lld::parallel::par, 0, 2049, [&range](size_t I) { ++range[I]; }); + for_each_n(parallel::par, 0, 2049, [&range](size_t I) { ++range[I]; }); uint32_t expected[2049]; std::fill(expected, expected + 2049, 2);