diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 07c62efe779..27c411e3223 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -19,6 +19,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { @@ -140,39 +141,32 @@ private: mix(uint32_t(Val)); } - template - struct addBitsImpl { - static void add(GeneralHash &Hash, const T *I, const T *E) { - Hash.addUnaligned( - reinterpret_cast(I), - reinterpret_cast(E)); + // Add a range of bytes from I to E. + void addBytes(const char *I, const char *E) { + uint32_t Data; + // Note that aliasing rules forbid us from dereferencing + // reinterpret_cast(I) even if I happens to be suitably + // aligned, so we use memcpy instead. + for (; E - I >= ptrdiff_t(sizeof Data); I += sizeof Data) { + // A clever compiler should be able to turn this memcpy into a single + // aligned or unaligned load (depending on the alignment of the type T + // that was used in the call to addBits). + std::memcpy(&Data, I, sizeof Data); + mix(Data); } - }; - - template - struct addBitsImpl { - static void add(GeneralHash &Hash, const T *I, const T *E) { - Hash.addAligned( - reinterpret_cast(I), - reinterpret_cast(E)); + if (I != E) { + Data = 0; + std::memcpy(&Data, I, E - I); + mix(Data); } - }; + } // Add a range of bits from I to E. template void addBits(const T *I, const T *E) { - addBitsImpl::Alignment_GreaterEqual_4Bytes>::add(*this, I, E); + addBytes(reinterpret_cast(I), + reinterpret_cast(E)); } - - // Add a range of uint32s - void addAligned(const uint32_t *I, const uint32_t *E) { - while (I < E) { - mix(*I++); - } - } - - // Add a possibly unaligned sequence of bytes. - void addUnaligned(const uint8_t *I, const uint8_t *E); }; } // end namespace llvm diff --git a/lib/Support/Hashing.cpp b/lib/Support/Hashing.cpp deleted file mode 100644 index 21fcdd7e7f8..00000000000 --- a/lib/Support/Hashing.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===-- llvm/ADT/Hashing.cpp - Utilities for hashing ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Hashing.h" - -namespace llvm { - -// Add a possibly unaligned sequence of bytes. -void GeneralHash::addUnaligned(const uint8_t *I, const uint8_t *E) { - ptrdiff_t Length = E - I; - if ((uintptr_t(I) & 3) == 0) { - while (Length > 3) { - mix(*reinterpret_cast(I)); - I += 4; - Length -= 4; - } - } else { - while (Length > 3) { - mix( - uint32_t(I[0]) + - (uint32_t(I[1]) << 8) + - (uint32_t(I[2]) << 16) + - (uint32_t(I[3]) << 24)); - I += 4; - Length -= 4; - } - } - - if (Length & 3) { - uint32_t Data = 0; - switch (Length & 3) { - case 3: Data |= uint32_t(I[2]) << 16; // fall through - case 2: Data |= uint32_t(I[1]) << 8; // fall through - case 1: Data |= uint32_t(I[0]); break; - } - mix(Data); - } -} - -}