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 <thiago.macieira@intel.com>
This commit is contained in:
Erik Verbruggen 2015-12-11 13:16:09 +01:00
parent 4417458d62
commit 6ffa3696e0

View File

@ -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 <typename Char>
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<const uchar *>(ptr);
const uchar *const e = p + (len * sizeof(Char));
#ifndef __ARM_FEATURE_UNALIGNED
if (Q_UNLIKELY(reinterpret_cast<quintptr>(p) & 7)) {
if ((sizeof(Char) == 1) && (reinterpret_cast<quintptr>(p) & 1) && (e - p > 0)) {
h = __crc32b(h, *p);
++p;
}
if ((reinterpret_cast<quintptr>(p) & 2) && (e >= p + 2)) {
h = __crc32h(h, *reinterpret_cast<const uint16_t *>(p));
p += 2;
}
if ((reinterpret_cast<quintptr>(p) & 4) && (e >= p + 4)) {
h = __crc32w(h, *reinterpret_cast<const uint32_t *>(p));
p += 4;
}
}
#endif
for ( ; p + 8 <= e; p += 8)
h = __crc32d(h, *reinterpret_cast<const uint64_t *>(p));
len = e - p;
if (len == 0)
return h;
if (len & 4) {
h = __crc32w(h, *reinterpret_cast<const uint32_t *>(p));
p += 4;
}
if (len & 2) {
h = __crc32h(h, *reinterpret_cast<const uint16_t *>(p));
p += 2;
}
if (sizeof(Char) == 1 && len & 1)
h = __crc32b(h, *p);
return h;
}
#else
static inline bool hasFastCrc32()
{