mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 20:29:53 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154264 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c0d18b6696
commit
5cd79bc14c
@ -505,13 +505,10 @@ namespace detail {
|
||||
/// 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
partial_store_size))
|
||||
abort();
|
||||
}
|
||||
return buffer_ptr;
|
||||
}
|
||||
|
||||
#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
|
||||
@ -570,11 +566,12 @@ public:
|
||||
/// 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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 ...Ts> hash_code hash_combine(const Ts &...args) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user