diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -19,6 +19,7 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "lld/Common/Arrays.h" #include "lld/Common/Filesystem.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" @@ -2972,19 +2973,6 @@ sec->writeTo(Out::bufferStart + sec->offset); } -// Split one uint8 array into small pieces of uint8 arrays. -static std::vector> split(ArrayRef arr, - size_t chunkSize) { - std::vector> ret; - while (arr.size() > chunkSize) { - ret.push_back(arr.take_front(chunkSize)); - arr = arr.drop_front(chunkSize); - } - if (!arr.empty()) - ret.push_back(arr); - return ret; -} - // Computes a hash value of Data using a given hash function. // In order to utilize multiple cores, we first split data into 1MB // chunks, compute a hash for each chunk, and then compute a hash value diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -20,12 +20,14 @@ #include "Target.h" #include "UnwindInfoSection.h" +#include "lld/Common/Arrays.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Parallel.h" #include "llvm/Support/Path.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/xxhash.h" @@ -920,10 +922,21 @@ osec->writeTo(buf + osec->fileOff); } +// In order to utilize multiple cores, we first split the buffer into chunks, +// compute a hash for each chunk, and then compute a hash value of the hash +// values. void Writer::writeUuid() { TimeTraceScope timeScope("Computing UUID"); - uint64_t digest = - xxHash64({buffer->getBufferStart(), buffer->getBufferEnd()}); + ArrayRef data{buffer->getBufferStart(), buffer->getBufferEnd()}; + unsigned chunkCount = parallel::strategy.compute_thread_count() * 10; + // Round-up integer division + size_t chunkSize = (data.size() + chunkCount - 1) / chunkCount; + std::vector> chunks = split(data, chunkSize); + std::vector hashes(chunks.size()); + parallelForEachN(0, chunks.size(), + [&](size_t i) { hashes[i] = xxHash64(chunks[i]); }); + uint64_t digest = xxHash64({reinterpret_cast(hashes.data()), + hashes.size() * sizeof(uint64_t)}); uuidCommand->writeUuid(digest); } diff --git a/lld/include/lld/Common/Arrays.h b/lld/include/lld/Common/Arrays.h new file mode 100644 --- /dev/null +++ b/lld/include/lld/Common/Arrays.h @@ -0,0 +1,32 @@ +//===- Arrays.h ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ARRAYS_H +#define LLD_ARRAYS_H + +#include "llvm/ADT/ArrayRef.h" + +#include + +namespace lld { +// Split one uint8 array into small pieces of uint8 arrays. +inline std::vector> split(llvm::ArrayRef arr, + size_t chunkSize) { + std::vector> ret; + while (arr.size() > chunkSize) { + ret.push_back(arr.take_front(chunkSize)); + arr = arr.drop_front(chunkSize); + } + if (!arr.empty()) + ret.push_back(arr); + return ret; +} + +} // namespace lld + +#endif