From 8d9d2a7b8568c4c067252e6ca9eea45de7a743a5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 23 Jan 2015 23:07:34 -0800 Subject: Optimize the Latin1 conversion code in the JSON parser with SSE2 This also reduces the number of variables modified in each loop from two (l and i) to one (just i) and avoids calling str.length() all the time. Those should be no-op changes, but why not help the optimizer? Change-Id: I8895c35f84d545dba45bffff13bc4147ae53eaab Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'src/corelib/json/qjson_p.h') diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index c2863f41a1..b8430cabf5 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -54,6 +54,8 @@ #include #include +#include "private/qsimd_p.h" + #include #include @@ -374,13 +376,34 @@ public: inline Latin1String &operator=(const QString &str) { - d->length = str.length(); + int len = d->length = str.length(); uchar *l = (uchar *)d->latin1; const ushort *uc = (const ushort *)str.unicode(); - for (int i = 0; i < str.length(); ++i) - *l++ = uc[i]; - while ((quintptr)l & 0x3) - *l++ = 0; + int i = 0; +#ifdef __SSE2__ + for ( ; i + 16 < len; i += 16) { + __m128i chunk1 = _mm_loadu_si128((__m128i*)&uc[i]); // load + __m128i chunk2 = _mm_loadu_si128((__m128i*)&uc[i + 8]); // load + // pack the two vector to 16 x 8bits elements + const __m128i result = _mm_packus_epi16(chunk1, chunk2); + _mm_storeu_si128((__m128i*)&l[i], result); // store + } +# ifdef Q_PROCESSOR_X86_64 + // we can do one more round, of 8 characters + if (i + 8 < len) { + __m128i chunk = _mm_loadu_si128((__m128i*)&uc[i]); // load + // pack with itself, we'll discard the high part anyway + chunk = _mm_packus_epi16(chunk, chunk); + // unaligned 64-bit store + *(quint64*)&l[i] = _mm_cvtsi128_si64(chunk); + i += 8; + } +# endif +#endif + for ( ; i < len; ++i) + l[i] = uc[i]; + for ( ; (quintptr)(l+i) & 0x3; ++i) + l[i] = 0; return *this; } -- cgit v1.2.3