[Support] Move Parallel algorithms from LLD to LLVM.

Differential Revision: https://reviews.llvm.org/D33024

llvm-svn: 302748
This commit is contained in:
Zachary Turner 2017-05-11 00:03:52 +00:00
parent ae0317e4a9
commit 3a57fbd6db
14 changed files with 73 additions and 107 deletions

View File

@ -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 <algorithm>
#include <atomic>

View File

@ -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;

View File

@ -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 <algorithm>

View File

@ -61,7 +61,7 @@
#include "Config.h"
#include "lld/Core/Parallel.h"
#include "llvm/Support/Parallel.h"
#include <functional>
namespace lld {
@ -70,17 +70,17 @@ namespace elf {
template <class IterTy, class FuncTy>
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 parallelForEachN(size_t Begin, size_t End,
std::function<void(size_t)> 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);
}
}
}

View File

@ -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 <condition_variable>
#include <functional>
#include <mutex>
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 Mutex;
mutable std::condition_variable Cond;
public:
explicit Latch(uint32_t count = 0) : Count(count) {}
~Latch() { sync(); }
void inc() {
std::unique_lock<std::mutex> lock(Mutex);
++Count;
}
void dec() {
std::unique_lock<std::mutex> lock(Mutex);
if (--Count == 0)
Cond.notify_all();
}
void sync() const {
std::unique_lock<std::mutex> lock(Mutex);
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 L;
public:
void spawn(std::function<void()> F);
void sync() const { L.sync(); }
};
}
#endif

View File

@ -12,7 +12,6 @@ add_lld_library(lldCore
Resolver.cpp
SymbolTable.cpp
TargetOptionsCommandFlags.cpp
TaskGroup.cpp
Writer.cpp
ADDITIONAL_HEADER_DIRS

View File

@ -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 <algorithm>
#include <set>
#include <utility>
@ -461,7 +461,7 @@ llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
});
std::vector<LayoutPass::SortKey> 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);
});

View File

@ -12,6 +12,5 @@ function(add_lld_unittest test_dirname)
target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS})
endfunction()
add_subdirectory(CoreTests)
add_subdirectory(DriverTests)
add_subdirectory(MachOTests)

View File

@ -1,7 +0,0 @@
add_lld_unittest(CoreTests
ParallelTest.cpp
)
target_link_libraries(CoreTests
lldCore ${LLVM_PTHREAD_LIB}
)

View File

@ -1,29 +1,70 @@
//===- 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 <algorithm>
#include <condition_variable>
#include <functional>
#include <mutex>
#if defined(_MSC_VER) && LLVM_ENABLE_THREADS
#pragma warning(push)
#pragma warning(disable : 4530)
#include <concrt.h>
#include <ppl.h>
#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<std::mutex> lock(Mutex);
++Count;
}
void dec() {
std::unique_lock<std::mutex> lock(Mutex);
if (--Count == 0)
Cond.notify_all();
}
void sync() const {
std::unique_lock<std::mutex> lock(Mutex);
Cond.wait(lock, [&] { return Count == 0; });
}
};
class TaskGroup {
Latch L;
public:
void spawn(std::function<void()> f);
void sync() const { L.sync(); }
};
}
namespace parallel {
struct sequential_execution_policy {};
@ -205,6 +246,6 @@ void for_each_n(parallel_execution_policy policy, IndexTy Begin, IndexTy End,
#endif
} // namespace parallel
} // End namespace lld
} // namespace llvm
#endif // LLD_CORE_PARALLEL_H
#endif // LLVM_SUPPORT_PARALLEL_H

View File

@ -81,6 +81,7 @@ add_llvm_library(LLVMSupport
MD5.cpp
NativeFormatting.cpp
Options.cpp
Parallel.cpp
PluginLoader.cpp
PrettyStackTrace.cpp
RandomNumberGenerator.cpp

View File

@ -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 <atomic>
#include <stack>
#include <thread>
#if defined(_MSC_VER) && LLVM_ENABLE_THREADS
#include <concrt.h>
#include <ppl.h>
#endif
using namespace lld;
using namespace llvm;
namespace {
@ -132,7 +127,7 @@ Executor *Executor::getDefaultExecutor() {
#endif
}
void TaskGroup::spawn(std::function<void()> F) {
void detail::TaskGroup::spawn(std::function<void()> F) {
L.inc();
Executor::getDefaultExecutor()->add([&, F] {
F();

View File

@ -36,6 +36,7 @@ add_llvm_unittest(SupportTests
MemoryBufferTest.cpp
MemoryTest.cpp
NativeFormatTests.cpp
ParallelTest.cpp
Path.cpp
ProcessTest.cpp
ProgramTest.cpp

View File

@ -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 <array>
#include <random>
uint32_t array[1024 * 1024];
using namespace llvm;
TEST(Parallel, sort) {
std::mt19937 randEngine;
std::uniform_int_distribution<uint32_t> dist;
@ -26,7 +28,7 @@ TEST(Parallel, sort) {
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 @@ TEST(Parallel, parallel_for) {
// 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);