summaryrefslogtreecommitdiffstats
path: root/util/charset/wide_sse41.cpp
diff options
context:
space:
mode:
authormihaild <[email protected]>2022-02-10 16:46:59 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:46:59 +0300
commit55fa8c7df8dba9a6fda8a807e529a9d04bd88580 (patch)
treeb83306b6e37edeea782e9eed673d89286c4fef35 /util/charset/wide_sse41.cpp
parent246417ad6168d3f7ab4a0cf1c79ba4259f7c45ae (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'util/charset/wide_sse41.cpp')
-rw-r--r--util/charset/wide_sse41.cpp78
1 files changed, 39 insertions, 39 deletions
diff --git a/util/charset/wide_sse41.cpp b/util/charset/wide_sse41.cpp
index 6859e9c44c4..d1f2a74851e 100644
--- a/util/charset/wide_sse41.cpp
+++ b/util/charset/wide_sse41.cpp
@@ -1,6 +1,6 @@
-#include <util/charset/wide.h>
+#include <util/charset/wide.h>
#include <util/system/types.h>
-
+
#ifdef SSE41_STUB
namespace NDetail {
@@ -13,21 +13,21 @@ namespace NDetail {
#else
#include <util/system/compiler.h>
-
+
#include <cstring>
#include <emmintrin.h>
#include <smmintrin.h>
-
-//processes to the first error, or until less then 16 bytes left
-//most code taken from https://woboq.com/blog/utf-8-processing-using-simd.html
-
+
+//processes to the first error, or until less then 16 bytes left
+//most code taken from https://woboq.com/blog/utf-8-processing-using-simd.html
+
//return dstAdvance 0 in case of problems
static Y_FORCE_INLINE ui32 Unpack16BytesIntoUtf16IfNoSurrogats(const unsigned char*& cur, __m128i& utf16Low, __m128i& utf16High) {
unsigned char curAligned[16];
-
+
memcpy(curAligned, cur, sizeof(__m128i));
__m128i chunk = _mm_load_si128(reinterpret_cast<const __m128i*>(curAligned));
-
+
//only ascii characters - simple copy
if (!_mm_movemask_epi8(chunk)) {
utf16Low = _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
@@ -35,68 +35,68 @@ static Y_FORCE_INLINE ui32 Unpack16BytesIntoUtf16IfNoSurrogats(const unsigned ch
cur += 16;
return 16;
}
-
+
__m128i chunkSigned = _mm_add_epi8(chunk, _mm_set1_epi8(0x80));
__m128i isAsciiMask = _mm_cmpgt_epi8(chunk, _mm_set1_epi8(0));
-
+
__m128i cond2 = _mm_cmplt_epi8(_mm_set1_epi8(0xc2 - 1 - 0x80), chunkSigned);
__m128i state = _mm_set1_epi8(0x0 | (char)0x80);
-
+
__m128i cond3 = _mm_cmplt_epi8(_mm_set1_epi8(0xe0 - 1 - 0x80), chunkSigned);
state = _mm_blendv_epi8(state, _mm_set1_epi8(0x2 | (char)0xc0), cond2);
-
+
int sourceAdvance;
__m128i shifts;
__m128i chunkLow, chunkHigh;
-
+
if (Y_LIKELY(!_mm_movemask_epi8(cond3))) {
//main case: no bloks of size 3 or 4
-
+
//rune len for start of multi-byte sequences (0 for b0... and b10..., 2 for b110..., etc.)
__m128i count = _mm_and_si128(state, _mm_set1_epi8(0x7));
-
+
__m128i countSub1 = _mm_subs_epu8(count, _mm_set1_epi8(0x1));
-
+
shifts = countSub1;
__m128i continuation1 = _mm_slli_si128(countSub1, 1);
-
+
shifts = _mm_add_epi8(shifts, _mm_slli_si128(shifts, 1));
shifts = _mm_add_epi8(shifts, _mm_slli_si128(shifts, 2));
-
+
__m128i counts = _mm_or_si128(count, continuation1);
-
+
__m128i isBeginMultibyteMask = _mm_cmpgt_epi8(count, _mm_set1_epi8(0));
__m128i needNoContinuationMask = _mm_cmpeq_epi8(continuation1, _mm_set1_epi8(0));
__m128i isBeginMask = _mm_add_epi8(isBeginMultibyteMask, isAsciiMask);
//each symbol should be exactly one of ascii, continuation or begin
__m128i okMask = _mm_cmpeq_epi8(isBeginMask, needNoContinuationMask);
-
+
if (_mm_movemask_epi8(okMask) != 0xFFFF) {
return 0;
}
-
+
shifts = _mm_add_epi8(shifts, _mm_slli_si128(shifts, 4));
-
+
__m128i mask = _mm_and_si128(state, _mm_set1_epi8(0xf8));
shifts = _mm_add_epi8(shifts, _mm_slli_si128(shifts, 8));
-
+
chunk = _mm_andnot_si128(mask, chunk); // from now on, we only have usefull bits
shifts = _mm_and_si128(shifts, _mm_cmplt_epi8(counts, _mm_set1_epi8(2))); // <=1
-
+
__m128i chunk_right = _mm_slli_si128(chunk, 1);
shifts = _mm_blendv_epi8(shifts, _mm_srli_si128(shifts, 1),
_mm_srli_si128(_mm_slli_epi16(shifts, 7), 1));
-
+
chunkLow = _mm_blendv_epi8(chunk,
_mm_or_si128(chunk, _mm_and_si128(_mm_slli_epi16(chunk_right, 6), _mm_set1_epi8(0xc0))),
_mm_cmpeq_epi8(counts, _mm_set1_epi8(1)));
-
+
chunkHigh = _mm_and_si128(chunk, _mm_cmpeq_epi8(counts, _mm_set1_epi8(2)));
-
+
shifts = _mm_blendv_epi8(shifts, _mm_srli_si128(shifts, 2),
_mm_srli_si128(_mm_slli_epi16(shifts, 6), 2));
chunkHigh = _mm_srli_epi32(chunkHigh, 2);
-
+
shifts = _mm_blendv_epi8(shifts, _mm_srli_si128(shifts, 4),
_mm_srli_si128(_mm_slli_epi16(shifts, 5), 4));
@@ -166,15 +166,15 @@ static Y_FORCE_INLINE ui32 Unpack16BytesIntoUtf16IfNoSurrogats(const unsigned ch
chunkHigh = _mm_or_si128(chunkHigh,
_mm_and_si128(_mm_and_si128(_mm_slli_epi32(chunk_right, 4), _mm_set1_epi8(0xf0)),
mask3));
-
+
int c = _mm_extract_epi16(counts, 7);
sourceAdvance = !(c & 0x0200) ? 16 : !(c & 0x02) ? 15
: 14;
}
-
+
shifts = _mm_blendv_epi8(shifts, _mm_srli_si128(shifts, 8),
_mm_srli_si128(_mm_slli_epi16(shifts, 4), 8));
-
+
chunkHigh = _mm_slli_si128(chunkHigh, 1);
__m128i shuf = _mm_add_epi8(shifts, _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
@@ -206,16 +206,16 @@ namespace NDetail {
_mm_store_si128(reinterpret_cast<__m128i*>(destAligned), utf16Low);
_mm_store_si128(reinterpret_cast<__m128i*>(destAligned) + 1, utf16High);
- memcpy(dest, destAligned, sizeof(__m128i) * 2);
+ memcpy(dest, destAligned, sizeof(__m128i) * 2);
dest += dstAdvance;
}
//The rest will be handled sequencially.
// Possible improvement: go back to the vectorized processing after the error or the 4 byte sequence
}
-
+
void UTF8ToWideImplSSE41(const unsigned char*& cur, const unsigned char* last, wchar32*& dest) noexcept {
alignas(16) wchar32 destAligned[16];
-
+
while (cur + 16 <= last) {
__m128i utf16Low;
__m128i utf16High;
@@ -238,10 +238,10 @@ namespace NDetail {
memcpy(dest, destAligned, sizeof(__m128i) * 4);
dest += dstAdvance;
- }
- //The rest will be handled sequencially.
+ }
+ //The rest will be handled sequencially.
// Possible improvement: go back to the vectorized processing after the error or the 4 byte sequence
- }
-}
+ }
+}
#endif