[lld] r302613 - [Core] Make parallel algorithms match C++ Parallelism TS.

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Wed May 10 09:27:14 PDT 2017


This broke Chromium's lld builds, e.g.
https://build.chromium.org/p/chromium.fyi/builders/ClangToTLinux/builds/8161

I'm not sure why it's not a problem on the regular LLVM buildbots, though.

On Tue, May 9, 2017 at 6:16 PM, Zachary Turner via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: zturner
> Date: Tue May  9 20:16:22 2017
> New Revision: 302613
>
> URL: http://llvm.org/viewvc/llvm-project?rev=302613&view=rev
> Log:
> [Core] Make parallel algorithms match C++ Parallelism TS.
>
> Differential Revision: https://reviews.llvm.org/D33016
>
> Modified:
>     lld/trunk/COFF/ICF.cpp
>     lld/trunk/COFF/MapFile.cpp
>     lld/trunk/COFF/Writer.cpp
>     lld/trunk/ELF/Threads.h
>     lld/trunk/include/lld/Core/Parallel.h
>     lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp
>     lld/trunk/unittests/CoreTests/ParallelTest.cpp
>
> Modified: lld/trunk/COFF/ICF.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/COFF/ICF.cpp (original)
> +++ lld/trunk/COFF/ICF.cpp Tue May  9 20:16:22 2017
> @@ -192,7 +192,7 @@ void ICF::forEachClass(std::function<voi
>    // Split sections into 256 shards and call Fn in parallel.
>    size_t NumShards = 256;
>    size_t Step = Chunks.size() / NumShards;
> -  parallel_for(size_t(0), NumShards, [&](size_t I) {
> +  for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
>      forEachClassRange(I * Step, (I + 1) * Step, Fn);
>    });
>    forEachClassRange(Step * NumShards, Chunks.size(), Fn);
>
> Modified: lld/trunk/COFF/MapFile.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MapFile.cpp?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/COFF/MapFile.cpp (original)
> +++ lld/trunk/COFF/MapFile.cpp Tue May  9 20:16:22 2017
> @@ -76,7 +76,7 @@ static SymbolMapTy getSectionSyms(ArrayR
>  static DenseMap<DefinedRegular *, std::string>
>  getSymbolStrings(ArrayRef<DefinedRegular *> Syms) {
>    std::vector<std::string> Str(Syms.size());
> -  parallel_for((size_t)0, Syms.size(), [&](size_t I) {
> +  for_each_n(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]);
>
> Modified: lld/trunk/COFF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/COFF/Writer.cpp (original)
> +++ lld/trunk/COFF/Writer.cpp Tue May  9 20:16:22 2017
> @@ -745,8 +745,8 @@ void Writer::writeSections() {
>      // ADD instructions).
>      if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
>        memset(SecBuf, 0xCC, Sec->getRawSize());
> -    parallel_for_each(Sec->getChunks().begin(), Sec->getChunks().end(),
> -                      [&](Chunk *C) { C->writeTo(SecBuf); });
> +    for_each(parallel::par, Sec->getChunks().begin(), Sec->getChunks().end(),
> +             [&](Chunk *C) { C->writeTo(SecBuf); });
>    }
>  }
>
> @@ -760,16 +760,14 @@ void Writer::sortExceptionTable() {
>    uint8_t *End = Begin + Sec->getVirtualSize();
>    if (Config->Machine == AMD64) {
>      struct Entry { ulittle32_t Begin, End, Unwind; };
> -    parallel_sort(
> -        (Entry *)Begin, (Entry *)End,
> -        [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
> +    sort(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; };
> -    parallel_sort(
> -        (Entry *)Begin, (Entry *)End,
> -        [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
> +    sort(parallel::par, (Entry *)Begin, (Entry *)End,
> +         [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
>      return;
>    }
>    errs() << "warning: don't know how to handle .pdata.\n";
>
> Modified: lld/trunk/ELF/Threads.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Threads.h?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Threads.h (original)
> +++ lld/trunk/ELF/Threads.h Tue May  9 20:16:22 2017
> @@ -71,19 +71,17 @@ namespace elf {
>  template <class IterTy, class FuncTy>
>  void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) {
>    if (Config->Threads)
> -    parallel_for_each(Begin, End, Fn);
> +    for_each(parallel::par, Begin, End, Fn);
>    else
> -    std::for_each(Begin, End, Fn);
> +    for_each(parallel::seq, Begin, End, Fn);
>  }
>
>  inline void parallelFor(size_t Begin, size_t End,
>                          std::function<void(size_t)> Fn) {
> -  if (Config->Threads) {
> -    parallel_for(Begin, End, Fn);
> -  } else {
> -    for (size_t I = Begin; I < End; ++I)
> -      Fn(I);
> -  }
> +  if (Config->Threads)
> +    for_each_n(parallel::par, Begin, End, Fn);
> +  else
> +    for_each_n(parallel::seq, Begin, End, Fn);
>  }
>  }
>  }
>
> Modified: lld/trunk/include/lld/Core/Parallel.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Parallel.h?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/Core/Parallel.h (original)
> +++ lld/trunk/include/lld/Core/Parallel.h Tue May  9 20:16:22 2017
> @@ -12,8 +12,9 @@
>
>  #include "lld/Core/LLVM.h"
>  #include "lld/Core/TaskGroup.h"
> -#include "llvm/Support/MathExtras.h"
> +#include "llvm/ADT/STLExtras.h"
>  #include "llvm/Config/llvm-config.h"
> +#include "llvm/Support/MathExtras.h"
>
>  #include <algorithm>
>
> @@ -24,25 +25,40 @@
>
>  namespace lld {
>
> -#if !LLVM_ENABLE_THREADS
> -template <class RandomAccessIterator, class Comparator>
> -void parallel_sort(
> -    RandomAccessIterator Start, RandomAccessIterator End,
> -    const Comparator &Comp = std::less<
> -        typename std::iterator_traits<RandomAccessIterator>::value_type>()) {
> -  std::sort(Start, End, Comp);
> -}
> -#elif defined(_MSC_VER)
> -// Use ppl parallel_sort on Windows.
> +namespace parallel {
> +struct sequential_execution_policy {};
> +struct parallel_execution_policy {};
> +
> +template <typename T>
> +struct is_execution_policy
> +    : public std::integral_constant<
> +          bool, llvm::is_one_of<T, sequential_execution_policy,
> +                                parallel_execution_policy>::value> {};
> +
> +constexpr sequential_execution_policy seq{};
> +constexpr parallel_execution_policy par{};
> +
> +#if LLVM_ENABLE_THREADS
> +
> +namespace detail {
> +
> +#if defined(_MSC_VER)
>  template <class RandomAccessIterator, class Comparator>
> -void parallel_sort(
> -    RandomAccessIterator Start, RandomAccessIterator End,
> -    const Comparator &Comp = std::less<
> -        typename std::iterator_traits<RandomAccessIterator>::value_type>()) {
> +void parallel_sort(RandomAccessIterator Start, RandomAccessIterator End,
> +                   const Comparator &Comp) {
>    concurrency::parallel_sort(Start, End, Comp);
>  }
> +template <class IterTy, class FuncTy>
> +void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
> +  concurrency::parallel_for_each(Begin, End, Fn);
> +}
> +
> +template <class IndexTy, class FuncTy>
> +void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
> +  concurrency::parallel_for(Begin, End, Fn);
> +}
> +
>  #else
> -namespace detail {
>  const ptrdiff_t MinParallelSize = 1024;
>
>  /// \brief Inclusive median.
> @@ -83,46 +99,15 @@ void parallel_quick_sort(RandomAccessIte
>    });
>    parallel_quick_sort(Pivot + 1, End, Comp, TG, Depth - 1);
>  }
> -}
>
>  template <class RandomAccessIterator, class Comparator>
> -void parallel_sort(
> -    RandomAccessIterator Start, RandomAccessIterator End,
> -    const Comparator &Comp = std::less<
> -        typename std::iterator_traits<RandomAccessIterator>::value_type>()) {
> +void parallel_sort(RandomAccessIterator Start, RandomAccessIterator End,
> +                   const Comparator &Comp) {
>    TaskGroup TG;
> -  detail::parallel_quick_sort(Start, End, Comp, TG,
> -                              llvm::Log2_64(std::distance(Start, End)) + 1);
> -}
> -#endif
> -
> -template <class T> void parallel_sort(T *Start, T *End) {
> -  parallel_sort(Start, End, std::less<T>());
> -}
> -
> -#if !LLVM_ENABLE_THREADS
> -template <class IterTy, class FuncTy>
> -void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
> -  std::for_each(Begin, End, Fn);
> -}
> -
> -template <class IndexTy, class FuncTy>
> -void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
> -  for (IndexTy I = Begin; I != End; ++I)
> -    Fn(I);
> -}
> -#elif defined(_MSC_VER)
> -// Use ppl parallel_for_each on Windows.
> -template <class IterTy, class FuncTy>
> -void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
> -  concurrency::parallel_for_each(Begin, End, Fn);
> +  parallel_quick_sort(Start, End, Comp, TG,
> +                      llvm::Log2_64(std::distance(Start, End)) + 1);
>  }
>
> -template <class IndexTy, class FuncTy>
> -void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
> -  concurrency::parallel_for(Begin, End, Fn);
> -}
> -#else
>  template <class IterTy, class FuncTy>
>  void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
>    // TaskGroup has a relatively high overhead, so we want to reduce
> @@ -142,7 +127,7 @@ void parallel_for_each(IterTy Begin, Ite
>  }
>
>  template <class IndexTy, class FuncTy>
> -void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
> +void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
>    ptrdiff_t TaskSize = (End - Begin) / 1024;
>    if (TaskSize == 0)
>      TaskSize = 1;
> @@ -160,7 +145,65 @@ void parallel_for(IndexTy Begin, IndexTy
>        Fn(J);
>    });
>  }
> +
> +#endif
> +
> +template <typename Iter>
> +using DefComparator =
> +    std::less<typename std::iterator_traits<Iter>::value_type>;
> +
> +} // namespace detail
>  #endif
> +
> +// sequential algorithm implementations.
> +template <class Policy, class RandomAccessIterator,
> +          class Comparator = detail::DefComparator<RandomAccessIterator>>
> +void sort(Policy policy, RandomAccessIterator Start, RandomAccessIterator End,
> +          const Comparator &Comp = Comparator()) {
> +  static_assert(is_execution_policy<Policy>::value,
> +                "Invalid execution policy!");
> +  std::sort(Start, End, Comp);
> +}
> +
> +template <class Policy, class IterTy, class FuncTy>
> +void for_each(Policy policy, IterTy Begin, IterTy End, FuncTy Fn) {
> +  static_assert(is_execution_policy<Policy>::value,
> +                "Invalid execution policy!");
> +  std::for_each(Begin, End, Fn);
> +}
> +
> +template <class Policy, class IndexTy, class FuncTy>
> +void for_each_n(Policy policy, IndexTy Begin, IndexTy End, FuncTy Fn) {
> +  static_assert(is_execution_policy<Policy>::value,
> +                "Invalid execution policy!");
> +  for (IndexTy I = Begin; I != End; ++I)
> +    Fn(I);
> +}
> +
> +// Parallel algorithm implementations, only available when LLVM_ENABLE_THREADS
> +// is true.
> +#if defined(LLVM_ENABLE_THREADS)
> +template <class RandomAccessIterator,
> +          class Comparator = detail::DefComparator<RandomAccessIterator>>
> +void sort(parallel_execution_policy policy, RandomAccessIterator Start,
> +          RandomAccessIterator End, const Comparator &Comp = Comparator()) {
> +  detail::parallel_sort(Start, End, Comp);
> +}
> +
> +template <class IterTy, class FuncTy>
> +void for_each(parallel_execution_policy policy, IterTy Begin, IterTy End,
> +              FuncTy Fn) {
> +  detail::parallel_for_each(Begin, End, Fn);
> +}
> +
> +template <class IndexTy, class FuncTy>
> +void for_each_n(parallel_execution_policy policy, IndexTy Begin, IndexTy End,
> +                FuncTy Fn) {
> +  detail::parallel_for_each_n(Begin, End, Fn);
> +}
> +#endif
> +
> +} // namespace parallel
>  } // End namespace lld
>
>  #endif // LLD_CORE_PARALLEL_H
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp Tue May  9 20:16:22 2017
> @@ -461,10 +461,10 @@ llvm::Error LayoutPass::perform(SimpleFi
>    });
>
>    std::vector<LayoutPass::SortKey> vec = decorate(atomRange);
> -  parallel_sort(vec.begin(), vec.end(),
> -      [&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool {
> -        return compareAtoms(l, r, _customSorter);
> -      });
> +  sort(parallel::par, vec.begin(), vec.end(),
> +       [&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool {
> +         return compareAtoms(l, r, _customSorter);
> +       });
>    DEBUG(checkTransitivity(vec, _customSorter));
>    undecorate(atomRange, vec);
>
>
> Modified: lld/trunk/unittests/CoreTests/ParallelTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CoreTests/ParallelTest.cpp?rev=302613&r1=302612&r2=302613&view=diff
> ==============================================================================
> --- lld/trunk/unittests/CoreTests/ParallelTest.cpp (original)
> +++ lld/trunk/unittests/CoreTests/ParallelTest.cpp Tue May  9 20:16:22 2017
> @@ -26,7 +26,7 @@ TEST(Parallel, sort) {
>    for (auto &i : array)
>      i = dist(randEngine);
>
> -  lld::parallel_sort(std::begin(array), std::end(array));
> +  sort(lld::parallel::par, std::begin(array), std::end(array));
>    ASSERT_TRUE(std::is_sorted(std::begin(array), std::end(array)));
>  }
>
> @@ -36,7 +36,7 @@ TEST(Parallel, parallel_for) {
>    // writing.
>    uint32_t range[2050];
>    std::fill(range, range + 2050, 1);
> -  lld::parallel_for(0, 2049, [&range](size_t I) { ++range[I]; });
> +  for_each_n(lld::parallel::par, 0, 2049, [&range](size_t I) { ++range[I]; });
>
>    uint32_t expected[2049];
>    std::fill(expected, expected + 2049, 2);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list