summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-01-09 20:35:59 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-01-18 21:38:12 -0800
commitd5fa6aa58c9a35ae9013f26e7e7641a9c67f5968 (patch)
tree7afa20315c0a87377161114ce853b647832b3725
parent3d70b291eda8d340616b562f9e7d5bff57e05d22 (diff)
QString: optimize equalStrings() with a template in ucstrncmp()
If the SIMD code has already determined that the byte content differs, we don't need to actually subtract the bytes we loaded from memory in vector operations to return a sorting result. Change-Id: I0e5f6bec596a4a78bd3bfffd16c908b2902e1b1b Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r--src/corelib/text/qstring.cpp33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 14d3e214a1..1f6dbd2547 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -115,6 +115,11 @@ const char16_t QString::_empty = 0;
qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
namespace {
+enum StringComparisonMode {
+ CompareStringsForEquality,
+ CompareStringsForOrdering
+};
+
inline bool qIsUpper(char ch)
{
return ch >= 'A' && ch <= 'Z';
@@ -1087,6 +1092,7 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const char16_t *a,
#endif
// Unicode case-sensitive compare two same-sized strings
+template <StringComparisonMode Mode>
static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
{
#ifndef __OPTIMIZE_SIZE__
@@ -1109,8 +1115,12 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
uint mask = ~uint(_mm_movemask_epi8(result));
if (ushort(mask) == 0)
return false;
- uint idx = qCountTrailingZeroBits(mask);
- retval = a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode();
+ if (Mode == CompareStringsForEquality) {
+ retval = 1;
+ } else {
+ uint idx = qCountTrailingZeroBits(mask);
+ retval = a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode();
+ }
return true;
};
@@ -1133,6 +1143,8 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
mask = ~mask;
if (mask) {
// found a different character
+ if (Mode == CompareStringsForEquality)
+ return 1;
uint idx = qCountTrailingZeroBits(mask);
return a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode();
}
@@ -1176,6 +1188,8 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
uint8_t r = ~(uint8_t)vaddvq_u16(vandq_u16(vceqq_u16(da, db), mask));
if (r) {
// found a different QChar
+ if (Mode == CompareStringsForEquality)
+ return 1;
uint idx = qCountTrailingZeroBits(r);
return (int)a[idx].unicode() - (int)b[idx].unicode();
}
@@ -1198,6 +1212,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
return 0;
}
+template <StringComparisonMode Mode>
static int ucstrncmp(const QChar *a, const char *b, size_t l)
{
const uchar *c = reinterpret_cast<const uchar *>(b);
@@ -1217,8 +1232,12 @@ static int ucstrncmp(const QChar *a, const char *b, size_t l)
uint mask = ~uint(_mm_movemask_epi8(result));
if (ushort(mask) == 0)
return false;
- uint idx = qCountTrailingZeroBits(mask);
- retval = uc[offset + idx / 2] - c[offset + idx / 2];
+ if (Mode == CompareStringsForEquality) {
+ retval = 1;
+ } else {
+ uint idx = qCountTrailingZeroBits(mask);
+ retval = uc[offset + idx / 2] - c[offset + idx / 2];
+ }
return true;
};
# endif
@@ -1254,6 +1273,8 @@ static int ucstrncmp(const QChar *a, const char *b, size_t l)
# endif
if (mask) {
// found a different character
+ if (Mode == CompareStringsForEquality)
+ return 1;
uint idx = qCountTrailingZeroBits(mask);
return uc[offset + idx / 2] - c[offset + idx / 2];
}
@@ -1325,7 +1346,7 @@ static bool ucstreq(const QChar *a, size_t alen, const Char2 *b, size_t blen)
if (a == b)
return true;
}
- return ucstrncmp(a, b, alen) == 0;
+ return ucstrncmp<CompareStringsForEquality>(a, b, alen) == 0;
}
// Unicode case-sensitive comparison
@@ -1337,7 +1358,7 @@ static int ucstrcmp(const QChar *a, size_t alen, const Char2 *b, size_t blen)
return 0;
}
const size_t l = qMin(alen, blen);
- int cmp = ucstrncmp(a, b, l);
+ int cmp = ucstrncmp<CompareStringsForOrdering>(a, b, l);
return cmp ? cmp : lencmp(alen, blen);
}