diff options
Diffstat (limited to 'src/corelib/tools/qhash.cpp')
-rw-r--r-- | src/corelib/tools/qhash.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index f14fac00b8..18d1cee0eb 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -60,6 +60,7 @@ #include <qbytearray.h> #include <qdatetime.h> #include <qbasicatomic.h> +#include <private/qsimd_p.h> #ifndef QT_BOOTSTRAPPED #include <qcoreapplication.h> @@ -93,10 +94,69 @@ QT_BEGIN_NAMESPACE (for instance, gcc 4.4 does that even at -O0). */ +#ifdef __SSE4_2__ +static inline bool hasFastCrc32() +{ + return true; +} + +template <typename Char> +static uint crc32(const Char *ptr, size_t len, uint h) +{ + // The CRC32 instructions from Nehalem calculate a 32-bit CRC32 checksum + const uchar *p = reinterpret_cast<const uchar *>(ptr); + const uchar *const e = p + (len * sizeof(Char)); +# ifdef Q_PROCESSOR_X86_64 + // The 64-bit instruction still calculates only 32-bit, but without this + // variable GCC 4.9 still tries to clear the high bits on every loop + qulonglong h2 = h; + + p += 8; + for ( ; p <= e; p += 8) + h2 = _mm_crc32_u64(h2, *reinterpret_cast<const qlonglong *>(p - 8)); + h = h2; + p -= 8; + + len = e - p; + if (len & 4) { + h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p)); + p += 4; + } +# else + p += 4; + for ( ; p <= e; p += 4) + h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p)); + p -= 4; + len = e - p; +# endif + if (len & 2) { + h = _mm_crc32_u16(h, *reinterpret_cast<const ushort *>(p)); + p += 2; + } + if (sizeof(Char) == 1 && len & 1) + h = _mm_crc32_u8(h, *p); + return h; +} +#else +static inline bool hasFastCrc32() +{ + return false; +} + +static uint crc32(...) +{ + Q_UNREACHABLE(); + return 0; +} +#endif + static inline uint hash(const uchar *p, int len, uint seed) Q_DECL_NOTHROW { uint h = seed; + if (hasFastCrc32()) + return crc32(p, size_t(len), h); + for (int i = 0; i < len; ++i) h = 31 * h + p[i]; @@ -107,6 +167,9 @@ static inline uint hash(const QChar *p, int len, uint seed) Q_DECL_NOTHROW { uint h = seed; + if (hasFastCrc32()) + return crc32(p, size_t(len), h); + for (int i = 0; i < len; ++i) h = 31 * h + p[i].unicode(); |