[llvm-commits] [llvm] r151247 - in /llvm/trunk: include/llvm/ADT/Hashing.h lib/Support/Hashing.cpp
Jay Foad
jay.foad at gmail.com
Thu Feb 23 01:16:04 PST 2012
Author: foad
Date: Thu Feb 23 03:16:04 2012
New Revision: 151247
URL: http://llvm.org/viewvc/llvm-project?rev=151247&view=rev
Log:
The implementation of GeneralHash::addBits broke C++ aliasing rules; fix
it with memcpy. This also fixes a problem on big-endian hosts, where
addUnaligned would return different results depending on the alignment
of the data.
Removed:
llvm/trunk/lib/Support/Hashing.cpp
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=151247&r1=151246&r2=151247&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Hashing.h (original)
+++ llvm/trunk/include/llvm/ADT/Hashing.h Thu Feb 23 03:16:04 2012
@@ -19,6 +19,7 @@
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include <cstring>
namespace llvm {
@@ -140,39 +141,32 @@
mix(uint32_t(Val));
}
- template<typename T, bool isAligned>
- struct addBitsImpl {
- static void add(GeneralHash &Hash, const T *I, const T *E) {
- Hash.addUnaligned(
- reinterpret_cast<const uint8_t *>(I),
- reinterpret_cast<const uint8_t *>(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<uint32_t *>(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<typename T>
- struct addBitsImpl<T, true> {
- static void add(GeneralHash &Hash, const T *I, const T *E) {
- Hash.addAligned(
- reinterpret_cast<const uint32_t *>(I),
- reinterpret_cast<const uint32_t *>(E));
+ if (I != E) {
+ Data = 0;
+ std::memcpy(&Data, I, E - I);
+ mix(Data);
}
- };
+ }
// Add a range of bits from I to E.
template<typename T>
void addBits(const T *I, const T *E) {
- addBitsImpl<T, AlignOf<T>::Alignment_GreaterEqual_4Bytes>::add(*this, I, E);
+ addBytes(reinterpret_cast<const char *>(I),
+ reinterpret_cast<const char *>(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
Removed: llvm/trunk/lib/Support/Hashing.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Hashing.cpp?rev=151246&view=auto
==============================================================================
--- llvm/trunk/lib/Support/Hashing.cpp (original)
+++ llvm/trunk/lib/Support/Hashing.cpp (removed)
@@ -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<const uint32_t *>(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);
- }
-}
-
-}
More information about the llvm-commits
mailing list