summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@theqtcompany.com>2015-12-11 13:16:09 +0100
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2016-01-13 09:05:06 +0000
commit6ffa3696e0bfa80215e3fe362d9ad01aa8a69442 (patch)
treec7184032a1869a4d5d553dc2915b2f9a90758c8d /src
parent4417458d62d1f75927b9f2e807e8843a49b01aa7 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qhash.cpp49
1 files changed, 49 insertions, 0 deletions
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 <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()
{