[llvm] b3c7d25 - [ADT] Use a C++17 fold expression in hash_combine (NFC) (#159901)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 20 09:51:19 PDT 2025
Author: Kazu Hirata
Date: 2025-09-20T09:51:14-07:00
New Revision: b3c7d25422355949227a12ded7515f5114db5bda
URL: https://github.com/llvm/llvm-project/commit/b3c7d25422355949227a12ded7515f5114db5bda
DIFF: https://github.com/llvm/llvm-project/commit/b3c7d25422355949227a12ded7515f5114db5bda.diff
LOG: [ADT] Use a C++17 fold expression in hash_combine (NFC) (#159901)
combine() combines hash values with recursion on variadic parameters.
This patch replaces the recursion with a C++17 fold expression:
(combine_data(length, buffer_ptr, buffer_end, get_hashable_data(args)),
...);
which expands to:
combine_data(length, buffer_ptr, buffer_end, get_hashable_data(a));
combine_data(length, buffer_ptr, buffer_end, get_hashable_data(b));
combine_data(length, buffer_ptr, buffer_end, get_hashable_data(c));
:
A key benefit of this change is the unification of the recursive step
and the base case. The argument processing and finalization logic now
exist as straight-line code within a single function.
combine_data now takes buffer_ptr by reference. This is necessary
because the previous assignment pattern:
buffer_ptr = combine_data(...)
is syntactically incompatible with a fold expression. The new pattern:
(combine_data(...), ...)
discards return values, so combine_data must update buffer_ptr
directly.
For readability, this patch does the bare minimum to use a fold
expression, leaving further cleanups to subsequent patches. For
example, buffer_ptr and buffer_end could become member variables, and
several comments that mention recursion still need updating.
Added:
Modified:
llvm/include/llvm/ADT/Hashing.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h
index 41a730e24a6b1..dffe3791e51c7 100644
--- a/llvm/include/llvm/ADT/Hashing.h
+++ b/llvm/include/llvm/ADT/Hashing.h
@@ -503,7 +503,8 @@ struct hash_combine_recursive_helper {
/// hash_state, empties it, and then merges the new chunk in. This also
/// handles cases where the data straddles the end of the buffer.
template <typename T>
- char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
+ char *combine_data(size_t &length, char *&buffer_ptr, char *buffer_end,
+ T data) {
if (!store_and_advance(buffer_ptr, buffer_end, data)) {
// Check for skew which prevents the buffer from being packed, and do
// a partial store into the buffer to fill it. This is only a concern
@@ -541,21 +542,15 @@ struct hash_combine_recursive_helper {
///
/// This function recurses through each argument, combining that argument
/// into a single hash.
- template <typename T, typename ...Ts>
+ template <typename... Ts>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T &arg, const Ts &...args) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
+ const Ts &...args) {
+ ((void)combine_data(length, buffer_ptr, buffer_end,
+ get_hashable_data(args)),
+ ...);
- // Recurse to the next argument.
- return combine(length, buffer_ptr, buffer_end, args...);
- }
-
- /// Base case for recursive, variadic combining.
- ///
- /// The base case when combining arguments recursively is reached when all
- /// arguments have been handled. It flushes the remaining buffer and
- /// constructs a hash_code.
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
+ // Finalize the hash by flushing any remaining data in the buffer.
+ //
// Check whether the entire set of values fit in the buffer. If so, we'll
// use the optimized short hashing routine and skip state entirely.
if (length == 0)
More information about the llvm-commits
mailing list