string 16<->8 bits conversion: SIMD on arm32

this adds emulation for 2 NEON commands that armv7 lacks
this increases conversion speed by around 50% in my simple tests

Change-Id: I4f52d353184e9a8d88089de60e17bd5670637c0c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
bb10
Nick Shaforostoff 2021-02-28 20:02:18 +01:00
parent d58d0bb970
commit 4f37cf2ce5
3 changed files with 20 additions and 4 deletions

View File

@ -274,6 +274,22 @@ QT_END_NAMESPACE
// __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection.
#define __ARM_NEON__
#endif
#ifndef Q_PROCESSOR_ARM_64 // vaddv is only available on Aarch64
inline uint16_t vaddvq_u16(uint16x8_t v8)
{
const uint64x2_t v2 = vpaddlq_u32(vpaddlq_u16(v8));
const uint64x1_t v1 = vadd_u64(vget_low_u64(v2), vget_high_u64(v2));
return vget_lane_u16(vreinterpret_u16_u64(v1), 0);
}
inline uint8_t vaddv_u8(uint8x8_t v8)
{
const uint64x1_t v1 = vpaddl_u32(vpaddl_u16(vpaddl_u8(v8)));
return vget_lane_u8(vreinterpret_u8_u64(v1), 0);
}
#endif
#endif
// AArch64/ARM64
#if defined(Q_PROCESSOR_ARM_V8) && defined(__ARM_FEATURE_CRC32)

View File

@ -333,7 +333,7 @@ const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
[=](int i) { return n[i] == c; },
[=](int i) { return n + i; });
# endif
#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
#elif defined(__ARM_NEON__)
const uint16x8_t vmask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
const uint16x8_t ch_vec = vdupq_n_u16(c);
for (const char16_t *next = n + 8; next <= e; n = next, next += 8) {
@ -1004,7 +1004,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
};
return UnrollTailLoop<3>::exec(l, 0, lambda, lambda);
#endif
#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
#ifdef __ARM_NEON__
if (l >= 8) {
const QChar *end = a + l;
const uint16x8_t mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };

View File

@ -61,7 +61,7 @@ enum { Endian = 0, Data = 1 };
static const uchar utf8bom[] = { 0xef, 0xbb, 0xbf };
#if (defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)) \
|| (defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64))
|| defined(__ARM_NEON__)
static Q_ALWAYS_INLINE uint qBitScanReverse(unsigned v) noexcept
{
#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
@ -360,7 +360,7 @@ static void simdCompareAscii(const char8_t *&src8, const char8_t *end8, const ch
src8 += offset;
src16 += offset;
}
#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
#elif defined(__ARM_NEON__)
static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const ushort *&src, const ushort *end)
{
uint16x8_t maxAscii = vdupq_n_u16(0x7f);