From 6ffa3696e0bfa80215e3fe362d9ad01aa8a69442 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 11 Dec 2015 13:16:09 +0100 Subject: ARMv8: Update qHash for strings to use the CRC32 instruction Same as the SSE4.2 implementation: use the (optional) ARMv8 crc32[bhwd] instruction to calculate hashes for strings. For Aarch64, support for the instruction is dynamically detected. For a 32bit ARM binary, dynamic detection is only done when the compiler is explicitly told to target ARMv8. When telling the compiler to target an other/older version, the crc32 code is not compiled. Change-Id: I51ebc1a4545dede4988247e75043f29a64c2a6c5 Reviewed-by: Thiago Macieira --- src/corelib/tools/qhash.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 7520158293..ec7ce94ed0 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -130,6 +130,55 @@ static uint crc32(const Char *ptr, size_t len, uint h) h = _mm_crc32_u8(h, *p); return h; } +#elif defined(Q_PROCESSOR_ARM_V8) +static inline bool hasFastCrc32() +{ + return qCpuHasFeature(CRC32); +} + +template +QT_FUNCTION_TARGET(CRC32) +static uint crc32(const Char *ptr, size_t len, uint h) +{ + // The crc32[whbd] instructions on Aarch64/Aarch32 calculate a 32-bit CRC32 checksum + const uchar *p = reinterpret_cast(ptr); + const uchar *const e = p + (len * sizeof(Char)); + +#ifndef __ARM_FEATURE_UNALIGNED + if (Q_UNLIKELY(reinterpret_cast(p) & 7)) { + if ((sizeof(Char) == 1) && (reinterpret_cast(p) & 1) && (e - p > 0)) { + h = __crc32b(h, *p); + ++p; + } + if ((reinterpret_cast(p) & 2) && (e >= p + 2)) { + h = __crc32h(h, *reinterpret_cast(p)); + p += 2; + } + if ((reinterpret_cast(p) & 4) && (e >= p + 4)) { + h = __crc32w(h, *reinterpret_cast(p)); + p += 4; + } + } +#endif + + for ( ; p + 8 <= e; p += 8) + h = __crc32d(h, *reinterpret_cast(p)); + + len = e - p; + if (len == 0) + return h; + if (len & 4) { + h = __crc32w(h, *reinterpret_cast(p)); + p += 4; + } + if (len & 2) { + h = __crc32h(h, *reinterpret_cast(p)); + p += 2; + } + if (sizeof(Char) == 1 && len & 1) + h = __crc32b(h, *p); + return h; +} #else static inline bool hasFastCrc32() { -- cgit v1.2.3