summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r--src/corelib/text/qstring.cpp72
1 files changed, 38 insertions, 34 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index e3c5de8fca..46ccae91b7 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -415,6 +415,42 @@ static Q_ALWAYS_INLINE __m128i mm_load8_zero_extend(const void *ptr)
return _mm_unpacklo_epi8(data, _mm_setzero_si128());
}
+[[maybe_unused]] ATTRIBUTE_NO_SANITIZE
+static qsizetype qustrlen_sse2(const char16_t *str) noexcept
+{
+ // find the 16-byte alignment immediately prior or equal to str
+ quintptr misalignment = quintptr(str) & 0xf;
+ Q_ASSERT((misalignment & 1) == 0);
+ const char16_t *ptr = str - (misalignment / 2);
+
+ // load 16 bytes and see if we have a null
+ // (aligned loads can never segfault)
+ const __m128i zeroes = _mm_setzero_si128();
+ __m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i comparison = _mm_cmpeq_epi16(data, zeroes);
+ quint32 mask = _mm_movemask_epi8(comparison);
+
+ // ignore the result prior to the beginning of str
+ mask >>= misalignment;
+
+ // Have we found something in the first block? Need to handle it now
+ // because of the left shift above.
+ if (mask)
+ return qCountTrailingZeroBits(quint32(mask)) / 2;
+
+ do {
+ ptr += 8;
+ data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
+
+ comparison = _mm_cmpeq_epi16(data, zeroes);
+ mask = _mm_movemask_epi8(comparison);
+ } while (mask == 0);
+
+ // found a null
+ uint idx = qCountTrailingZeroBits(quint32(mask));
+ return ptr - str + idx / 2;
+}
+
// Scans from \a ptr to \a end until \a maskval is non-zero. Returns true if
// the no non-zero was found. Returns false and updates \a ptr to point to the
// first 16-bit word that has any bit set (note: if the input is 8-bit, \a ptr
@@ -517,48 +553,16 @@ static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
}
#endif
-ATTRIBUTE_NO_SANITIZE
qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
{
- qsizetype result = 0;
-
#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
- // find the 16-byte alignment immediately prior or equal to str
- quintptr misalignment = quintptr(str) & 0xf;
- Q_ASSERT((misalignment & 1) == 0);
- const char16_t *ptr = str - (misalignment / 2);
-
- // load 16 bytes and see if we have a null
- // (aligned loads can never segfault)
- const __m128i zeroes = _mm_setzero_si128();
- __m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i comparison = _mm_cmpeq_epi16(data, zeroes);
- quint32 mask = _mm_movemask_epi8(comparison);
-
- // ignore the result prior to the beginning of str
- mask >>= misalignment;
-
- // Have we found something in the first block? Need to handle it now
- // because of the left shift above.
- if (mask)
- return qCountTrailingZeroBits(quint32(mask)) / 2;
-
- do {
- ptr += 8;
- data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
-
- comparison = _mm_cmpeq_epi16(data, zeroes);
- mask = _mm_movemask_epi8(comparison);
- } while (mask == 0);
-
- // found a null
- uint idx = qCountTrailingZeroBits(quint32(mask));
- return ptr - str + idx / 2;
+ return qustrlen_sse2(str);
#endif
if (sizeof(wchar_t) == sizeof(char16_t))
return wcslen(reinterpret_cast<const wchar_t *>(str));
+ qsizetype result = 0;
while (*str++)
++result;
return result;