[llvm-commits] [llvm] r154264 - /llvm/trunk/include/llvm/ADT/Hashing.h

Chandler Carruth chandlerc at gmail.com
Sat Apr 7 13:01:31 PDT 2012


Author: chandlerc
Date: Sat Apr  7 15:01:31 2012
New Revision: 154264

URL: http://llvm.org/viewvc/llvm-project?rev=154264&view=rev
Log:
Perform partial SROA on the helper hashing structure. I really wish the
optimizers could do this for us, but expecting partial SROA of classes
with template methods through cloning is probably expecting too much
heroics. With this change, the begin/end pointer pairs which indicate
the status of each loop iteration are actually passed directly into each
layer of the combine_data calls, and the inliner has a chance to see
when most of the combine_data function could be deleted by inlining.
Similarly for 'length'.

We have to be careful to limit the places where in/out reference
parameters are used as those will also defeat the inliner / optimizers
from properly propagating constants.

With this change, LLVM is able to fully inline and unroll the hash
computation of small sets of values, such as two or three pointers.
These now decompose into essentially straight-line code with no loops or
function calls.

There is still one code quality problem to be solved with the hashing --
LLVM is failing to nuke the alloca. It removes all loads from the
alloca, leaving only lifetime intrinsics and dead(!!) stores to the
alloca. =/ Very unfortunate.

Modified:
    llvm/trunk/include/llvm/ADT/Hashing.h

Modified: llvm/trunk/include/llvm/ADT/Hashing.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Hashing.h?rev=154264&r1=154263&r2=154264&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Hashing.h (original)
+++ llvm/trunk/include/llvm/ADT/Hashing.h Sat Apr  7 15:01:31 2012
@@ -505,13 +505,10 @@
 /// recursive combining of arguments used in hash_combine. It is particularly
 /// useful at minimizing the code in the recursive calls to ease the pain
 /// caused by a lack of variadic functions.
-class hash_combine_recursive_helper {
-  const size_t seed;
+struct hash_combine_recursive_helper {
   char buffer[64];
-  char *const buffer_end;
-  char *buffer_ptr;
-  size_t length;
   hash_state state;
+  const size_t seed;
 
 public:
   /// \brief Construct a recursive hash combining helper.
@@ -519,10 +516,7 @@
   /// This sets up the state for a recursive hash combine, including getting
   /// the seed and buffer setup.
   hash_combine_recursive_helper()
-    : seed(get_execution_seed()),
-      buffer_end(buffer + array_lengthof(buffer)),
-      buffer_ptr(buffer),
-      length(0) {}
+    : seed(get_execution_seed()) {}
 
   /// \brief Combine one chunk of data into the current in-flight hash.
   ///
@@ -530,7 +524,8 @@
   /// the data. If the buffer is full, it hashes the buffer into its
   /// 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> void combine_data(T data) {
+  template <typename T>
+  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
@@ -561,6 +556,7 @@
                              partial_store_size))
         abort();
     }
+    return buffer_ptr;
   }
 
 #if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
@@ -570,11 +566,12 @@
   /// This function recurses through each argument, combining that argument
   /// into a single hash.
   template <typename T, typename ...Ts>
-  hash_code combine(const T &arg, const Ts &...args) {
-    combine_data( get_hashable_data(arg));
+  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));
 
     // Recurse to the next argument.
-    return combine(args...);
+    return combine(length, buffer_ptr, buffer_end, args...);
   }
 
 #else
@@ -583,37 +580,43 @@
 
   template <typename T1, typename T2, typename T3, typename T4, typename T5,
             typename T6>
-  hash_code combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1, const T2 &arg2, const T3 &arg3,
                     const T4 &arg4, const T5 &arg5, const T6 &arg6) {
-    combine_data(get_hashable_data(arg1));
-    return combine(arg2, arg3, arg4, arg5, arg6);
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6);
   }
   template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  hash_code combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1, const T2 &arg2, const T3 &arg3,
                     const T4 &arg4, const T5 &arg5) {
-    combine_data(get_hashable_data(arg1));
-    return combine(arg2, arg3, arg4, arg5);
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5);
   }
   template <typename T1, typename T2, typename T3, typename T4>
-  hash_code combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1, const T2 &arg2, const T3 &arg3,
                     const T4 &arg4) {
-    combine_data(get_hashable_data(arg1));
-    return combine(arg2, arg3, arg4);
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4);
   }
   template <typename T1, typename T2, typename T3>
-  hash_code combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
-    combine_data(get_hashable_data(arg1));
-    return combine(arg2, arg3);
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1, const T2 &arg2, const T3 &arg3) {
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end, arg2, arg3);
   }
   template <typename T1, typename T2>
-  hash_code combine(const T1 &arg1, const T2 &arg2) {
-    combine_data(get_hashable_data(arg1));
-    return combine(arg2);
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1, const T2 &arg2) {
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end, arg2);
   }
   template <typename T1>
-  hash_code combine(const T1 &arg1) {
-    combine_data(get_hashable_data(arg1));
-    return combine();
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T1 &arg1) {
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
+    return combine(length, buffer_ptr, buffer_end);
   }
 
 #endif
@@ -623,7 +626,7 @@
   /// 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() {
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
     // 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)
@@ -663,7 +666,7 @@
 template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
   // Recursively hash each argument using a helper class.
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(args...);
+  return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
 }
 
 #else
@@ -674,36 +677,39 @@
 template <typename T1, typename T2, typename T3, typename T4, typename T5,
           typename T6>
 hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
-                  const T4 &arg4, const T5 &arg5, const T6 &arg6) {
+                       const T4 &arg4, const T5 &arg5, const T6 &arg6) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1, arg2, arg3, arg4, arg5, arg6);
+  return helper.combine(0, helper.buffer, helper.buffer + 64,
+                        arg1, arg2, arg3, arg4, arg5, arg6);
 }
 template <typename T1, typename T2, typename T3, typename T4, typename T5>
 hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
-                  const T4 &arg4, const T5 &arg5) {
+                       const T4 &arg4, const T5 &arg5) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1, arg2, arg3, arg4, arg5);
+  return helper.combine(0, helper.buffer, helper.buffer + 64,
+                        arg1, arg2, arg3, arg4, arg5);
 }
 template <typename T1, typename T2, typename T3, typename T4>
 hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
-                  const T4 &arg4) {
+                       const T4 &arg4) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1, arg2, arg3, arg4);
+  return helper.combine(0, helper.buffer, helper.buffer + 64,
+                        arg1, arg2, arg3, arg4);
 }
 template <typename T1, typename T2, typename T3>
 hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1, arg2, arg3);
+  return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3);
 }
 template <typename T1, typename T2>
 hash_code hash_combine(const T1 &arg1, const T2 &arg2) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1, arg2);
+  return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2);
 }
 template <typename T1>
 hash_code hash_combine(const T1 &arg1) {
   ::llvm::hashing::detail::hash_combine_recursive_helper helper;
-  return helper.combine(arg1);
+  return helper.combine(0, helper.buffer, helper.buffer + 64, arg1);
 }
 
 #endif





More information about the llvm-commits mailing list