summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-08-20 14:22:44 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-09-13 16:19:45 +0000
commit3b61cd6ad738b8479bf216dcf736bb935e8812df (patch)
treede0c9c06a6d426c9c91e93342cf02208eb11b8ff /src/corelib
parentad8a48e8f1b336099eab2a00c1c1e59abad8e717 (diff)
QStringView: De-inline the length calculation so we can use SSE2
Performance is more important in this case than the theoretical benefit of constexpr. This commit implements the SSE2 search for 16-bit null and it might be possible to implement the equivalent for AArch64 (investigation required). It also adds a fallback to wcslen() for systems where wchar_t is short (non-x86 Windows or 32-bit x86 build with -no-sse2). We can re-add the constexpr loop once the C++ language has a way of overloading constexpr and non-constexpr. GCC has a non-standard way to do that with __builtin_constant_p, which is also implemented in this commit, but note that the inline function is still not constexpr. Change-Id: I6e9274c1e7444ad48c81fffd14dcaacafda5ebdc Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/tools/qstring.cpp38
-rw-r--r--src/corelib/tools/qstringalgorithms.h2
-rw-r--r--src/corelib/tools/qstringview.h22
3 files changed, 52 insertions, 10 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 3826d7531a..a0c309c1cf 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -72,6 +72,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <wchar.h>
#include "qchar.cpp"
#include "qstringmatcher.cpp"
@@ -159,6 +160,43 @@ static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::Ca
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
+qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW
+{
+ qssize_t result = 0;
+
+#ifdef __SSE2__
+ // progress until we get an aligned pointer
+ const ushort *ptr = str;
+ while (*ptr && quintptr(ptr) % 16)
+ ++ptr;
+ if (*ptr == 0)
+ return ptr - str;
+
+ // load 16 bytes and see if we have a null
+ // (aligned loads can never segfault)
+ int mask;
+ const __m128i zeroes = _mm_setzero_si128();
+ do {
+ __m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
+ ptr += 8;
+
+ __m128i 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 - 8 + idx / 2;
+#endif
+
+ if (sizeof(wchar_t) == sizeof(ushort))
+ return wcslen(reinterpret_cast<const wchar_t *>(str));
+
+ while (*str++)
+ ++result;
+ return result;
+}
+
#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
namespace {
template <uint MaxCount> struct UnrollTailLoop
diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h
index e1b8b90428..eaa7207bec 100644
--- a/src/corelib/tools/qstringalgorithms.h
+++ b/src/corelib/tools/qstringalgorithms.h
@@ -53,6 +53,8 @@ class QLatin1String;
class QStringView;
template <typename T> class QVector;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW;
+
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
index 24be441b00..764da71d0b 100644
--- a/src/corelib/tools/qstringview.h
+++ b/src/corelib/tools/qstringview.h
@@ -143,20 +143,22 @@ private:
{
return qssize_t(N - 1);
}
+
template <typename Char>
- static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
+ static qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
{
- qssize_t result = 0;
- while (*str++)
- ++result;
- return result;
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+ if (__builtin_constant_p(*str)) {
+ qssize_t result = 0;
+ while (*str++)
+ ++result;
+ }
+#endif
+ return qustrlen(reinterpret_cast<const ushort *>(str));
}
- static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
+ static qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
{
- qssize_t result = 0;
- while (!str++->isNull())
- ++result;
- return result;
+ return qustrlen(reinterpret_cast<const ushort *>(str));
}
template <typename Char>