summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2011-03-19 15:25:12 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2011-03-22 14:51:58 (GMT)
commitadbb2aed4e2fcbc506e3d497001530e1a177aafc (patch)
tree9321d5d63f69bdd08f8d89282ab3ab6adbaea585
parent56ac27bd620768e0b130a3ce8de93c1a8524c6c6 (diff)
downloadQt-adbb2aed4e2fcbc506e3d497001530e1a177aafc.zip
Qt-adbb2aed4e2fcbc506e3d497001530e1a177aafc.tar.gz
Qt-adbb2aed4e2fcbc506e3d497001530e1a177aafc.tar.bz2
Add an UTF-8 conversion optimised for ASCII using SSE2
This code is 2x faster than the original UTF-8 code and within 35% of the pure Latin1 code
-rw-r--r--tests/benchmarks/corelib/tools/qstring/main.cpp55
1 files changed, 54 insertions, 1 deletions
diff --git a/tests/benchmarks/corelib/tools/qstring/main.cpp b/tests/benchmarks/corelib/tools/qstring/main.cpp
index 27d4dff..e05915d 100644
--- a/tests/benchmarks/corelib/tools/qstring/main.cpp
+++ b/tests/benchmarks/corelib/tools/qstring/main.cpp
@@ -2052,6 +2052,58 @@ int fromUtf8_optimised_for_ascii(ushort *qch, const char *chars, int len)
return dst + counter - qch;
}
+int fromUtf8_sse2_optimised_for_ascii(ushort *qch, const char *chars, int len)
+{
+ if (len > 3
+ && (uchar)chars[0] == 0xef && (uchar)chars[1] == 0xbb && (uchar)chars[2] == 0xbf) {
+ // starts with a byte order mark
+ chars += 3;
+ len -= 3;
+ }
+
+ qptrdiff counter = 0;
+ ushort *dst = qch;
+
+ len -= 16;
+ const __m128i nullMask = _mm_set1_epi32(0);
+ while (counter < len) {
+ const __m128i chunk = _mm_loadu_si128((__m128i*)(chars + counter)); // load
+
+ // unpack the first 8 bytes, padding with zeros
+ const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + counter), firstHalf); // store
+
+ // unpack the last 8 bytes, padding with zeros
+ const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + counter + 8), secondHalf); // store
+
+ ushort highbytes = _mm_movemask_epi8(chunk);
+ if (!highbytes) {
+ counter += 16;
+ continue;
+ }
+
+ // UTF-8 character found
+ // which one?
+ counter += bsf_nonzero(highbytes);
+ extract_utf8_multibyte(dst, chars, counter, len);
+ }
+ len += 16;
+
+ while (counter < len) {
+ uchar ch = chars[counter];
+ if ((ch & 0x80) == 0) {
+ dst[counter] = ch;
+ ++counter;
+ continue;
+ }
+
+ // UTF-8 character found
+ extract_utf8_multibyte(dst, chars, counter, len);
+ }
+ return dst + counter - qch;
+}
+
void tst_QString::fromUtf8Alternatives_data() const
{
QTest::addColumn<FromUtf8Function>("function");
@@ -2060,7 +2112,8 @@ void tst_QString::fromUtf8Alternatives_data() const
QTest::newRow("latin1-qt4.7") << &fromUtf8_latin1_qt47;
QTest::newRow("qt-4.7") << &fromUtf8_qt47;
QTest::newRow("qt-4.7-stateless") << &fromUtf8_qt47_stateless;
- QTest::newRow("optimised-for-ascii") << &fromUtf8_optimised_for_ascii;
+ QTest::newRow("optimized-for-ascii") << &fromUtf8_optimised_for_ascii;
+ QTest::newRow("sse2-optimized-for-ascii") << &fromUtf8_sse2_optimised_for_ascii;
}
extern StringData fromUtf8Data;