Skip to content

Commit 66a8067

Browse files
committed
Small performance improvements
1 parent 8979194 commit 66a8067

3 files changed

Lines changed: 121 additions & 4 deletions

File tree

src/Memory.hpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,68 @@ static KANZI_ALWAYS_INLINE uint64 knz_bswap64(uint64 x) {
248248

249249
#endif
250250

251+
static KANZI_ALWAYS_INLINE void memXor8(byte* dst, const byte* x, const byte* y)
252+
{
253+
#if !defined(NO_INTRINSICS) && (defined(__ARM_NEON) || defined(__aarch64__))
254+
vst1_u8(reinterpret_cast<uint8_t*>(dst),
255+
veor_u8(vld1_u8(reinterpret_cast<const uint8_t*>(x)),
256+
vld1_u8(reinterpret_cast<const uint8_t*>(y))));
257+
#elif !defined(NO_INTRINSICS) && defined(__AVX512F__)
258+
const __mmask8 mask = 0x01;
259+
const __m512i a = _mm512_maskz_loadu_epi64(mask, x);
260+
const __m512i b = _mm512_maskz_loadu_epi64(mask, y);
261+
_mm512_mask_storeu_epi64(dst, mask, _mm512_xor_si512(a, b));
262+
#elif !defined(NO_INTRINSICS) && defined(__AVX2__)
263+
const __m256i mask = _mm256_set_epi64x(0, 0, 0, -1);
264+
const __m256i a = _mm256_maskload_epi64(reinterpret_cast<const long long*>(x), mask);
265+
const __m256i b = _mm256_maskload_epi64(reinterpret_cast<const long long*>(y), mask);
266+
_mm256_maskstore_epi64(reinterpret_cast<long long*>(dst), mask, _mm256_xor_si256(a, b));
267+
#elif !defined(NO_INTRINSICS) && defined(__SSE2__)
268+
const __m128i a = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(x));
269+
const __m128i b = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(y));
270+
_mm_storel_epi64(reinterpret_cast<__m128i*>(dst), _mm_xor_si128(a, b));
271+
#else
272+
uint64 a;
273+
uint64 b;
274+
memcpy(&a, x, sizeof(uint64));
275+
memcpy(&b, y, sizeof(uint64));
276+
a ^= b;
277+
memcpy(dst, &a, sizeof(uint64));
278+
#endif
279+
}
280+
281+
static KANZI_ALWAYS_INLINE void memXor16(byte* dst, const byte* x, const byte* y)
282+
{
283+
#if !defined(NO_INTRINSICS) && (defined(__ARM_NEON) || defined(__aarch64__))
284+
vst1q_u8(reinterpret_cast<uint8_t*>(dst),
285+
veorq_u8(vld1q_u8(reinterpret_cast<const uint8_t*>(x)),
286+
vld1q_u8(reinterpret_cast<const uint8_t*>(y))));
287+
#elif !defined(NO_INTRINSICS) && defined(__AVX512F__)
288+
const __mmask8 mask = 0x03;
289+
const __m512i a = _mm512_maskz_loadu_epi64(mask, x);
290+
const __m512i b = _mm512_maskz_loadu_epi64(mask, y);
291+
_mm512_mask_storeu_epi64(dst, mask, _mm512_xor_si512(a, b));
292+
#elif !defined(NO_INTRINSICS) && defined(__AVX2__)
293+
const __m256i mask = _mm256_set_epi64x(0, 0, -1, -1);
294+
const __m256i a = _mm256_maskload_epi64(reinterpret_cast<const long long*>(x), mask);
295+
const __m256i b = _mm256_maskload_epi64(reinterpret_cast<const long long*>(y), mask);
296+
_mm256_maskstore_epi64(reinterpret_cast<long long*>(dst), mask, _mm256_xor_si256(a, b));
297+
#elif !defined(NO_INTRINSICS) && defined(__SSE2__)
298+
const __m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i*>(x));
299+
const __m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i*>(y));
300+
_mm_storeu_si128(reinterpret_cast<__m128i*>(dst), _mm_xor_si128(a, b));
301+
#else
302+
memXor8(dst, x, y);
303+
memXor8(dst + 8, x + 8, y + 8);
304+
#endif
305+
}
306+
251307
#define KANZI_MEM_EQ4(x, y) (::kanzi::memEq4((x), (y)))
252308
#define KANZI_MEM_EQ8(x, y) (::kanzi::memEq8((x), (y)))
253309
#define KANZI_MEM_CP8(dst, src) (::kanzi::memCp8((dst), (src)))
254310
#define KANZI_MEM_CP16(dst, src) (::kanzi::memCp16((dst), (src)))
311+
#define KANZI_MEM_XOR8(dst, x, y) (::kanzi::memXor8((dst), (x), (y)))
312+
#define KANZI_MEM_XOR16(dst, x, y) (::kanzi::memXor16((dst), (x), (y)))
255313

256314
// Detect host endianness
257315

src/entropy/TPAQPredictor.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ limitations under the License.
1919

2020
#include <cstring>
2121
#include "../Context.hpp"
22+
#include "../Global.hpp"
2223
#include "../Predictor.hpp"
2324
#include "../Memory.hpp"
2425
#include "AdaptiveProbMap.hpp"
@@ -559,6 +560,33 @@ namespace kanzi
559560
if ((_matchPos != 0) && (uint(_pos - _matchPos) <= _bufferMask)) {
560561
int r = _matchLen + 2;
561562

563+
// Compare four pairs at once when both logical ranges are physically
564+
// contiguous. Wrapping ranges use the scalar path below.
565+
while (r + 6 <= MAX_LENGTH) {
566+
const uint p0 = uint(_pos - r - 7) & _bufferMask;
567+
const uint p1 = uint(_matchPos - r - 7) & _bufferMask;
568+
569+
if ((p0 > _bufferMask - 7) || (p1 > _bufferMask - 7))
570+
break;
571+
572+
// Read as big endian so the newest byte is in the low bits.
573+
// This makes trailingZeros() identify the first mismatch in
574+
// the same direction as the original pair-by-pair scan.
575+
const uint64 diff = uint64(BigEndian::readLong64(&_buffer[p0])) ^
576+
uint64(BigEndian::readLong64(&_buffer[p1]));
577+
578+
if (diff != 0) {
579+
// Round down to a complete pair. The scalar loop below
580+
// locates the exact mismatching pair.
581+
r += (Global::trailingZeros(diff) >> 4) << 1;
582+
break;
583+
}
584+
585+
r += 8;
586+
}
587+
588+
// Locate the first mismatching pair and preserve the original
589+
// even-length match semantics.
562590
while (r <= MAX_LENGTH) {
563591
if ((_buffer[(_pos - r - 1) & _bufferMask]) != (_buffer[(_matchPos - r - 1) & _bufferMask]))
564592
break;

src/transform/FSDCodec.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ limitations under the License.
1818
#include "FSDCodec.hpp"
1919
#include "../Global.hpp"
2020
#include "../Magic.hpp"
21+
#include "../Memory.hpp"
2122

2223
using namespace kanzi;
2324
using namespace std;
@@ -232,10 +233,11 @@ bool FSDCodec::forward(SliceArray<kanzi::byte>& input, SliceArray<kanzi::byte>&
232233
// Emit modified bytes
233234
if (mode == DELTA_CODING) {
234235
while ((srcIdx < srcEnd) && (dstIdx < dstEnd - 1)) {
235-
const int delta = 127 + int(src[srcIdx]) - int(src[srcIdx - dist]);
236+
const int delta = int(src[srcIdx]) - int(src[srcIdx - dist]);
237+
const uint zigzag = uint(delta + 127);
236238

237-
if ((delta >= 0) && (delta < 255)) {
238-
dst[dstIdx++] = kanzi::byte(ZIGZAG1[delta]); // zigzag encode delta
239+
if (zigzag < 255) {
240+
dst[dstIdx++] = kanzi::byte(ZIGZAG1[zigzag]);
239241
srcIdx++;
240242
continue;
241243
}
@@ -247,6 +249,18 @@ bool FSDCodec::forward(SliceArray<kanzi::byte>& input, SliceArray<kanzi::byte>&
247249
}
248250
}
249251
else { // mode == XOR_CODING
252+
while (srcIdx + 16 <= srcEnd) {
253+
KANZI_MEM_XOR16(&dst[dstIdx], &src[srcIdx], &src[srcIdx - dist]);
254+
srcIdx += 16;
255+
dstIdx += 16;
256+
}
257+
258+
while (srcIdx + 8 <= srcEnd) {
259+
KANZI_MEM_XOR8(&dst[dstIdx], &src[srcIdx], &src[srcIdx - dist]);
260+
srcIdx += 8;
261+
dstIdx += 8;
262+
}
263+
250264
while (srcIdx < srcEnd) {
251265
dst[dstIdx++] = src[srcIdx] ^ src[srcIdx - dist];
252266
srcIdx++;
@@ -321,7 +335,9 @@ bool FSDCodec::inverse(SliceArray<kanzi::byte>& input, SliceArray<kanzi::byte>&
321335
if (mode == DELTA_CODING) {
322336
while ((srcIdx < srcEnd) && (dstIdx < dstEnd)) {
323337
if (src[srcIdx] != ESCAPE_TOKEN) {
324-
dst[dstIdx] = kanzi::byte(int(dst[dstIdx - dist]) + ZIGZAG2[int(src[srcIdx])]);
338+
const int value = int(src[srcIdx]);
339+
const int delta = (value >> 1) ^ -(value & 1);
340+
dst[dstIdx] = kanzi::byte(int(dst[dstIdx - dist]) + delta);
325341
srcIdx++;
326342
dstIdx++;
327343
continue;
@@ -338,6 +354,21 @@ bool FSDCodec::inverse(SliceArray<kanzi::byte>& input, SliceArray<kanzi::byte>&
338354
}
339355
}
340356
else if (mode == XOR_CODING) {
357+
if (dist == 16) {
358+
while ((srcIdx + 16 <= srcEnd) && (dstIdx + 16 <= dstEnd)) {
359+
KANZI_MEM_XOR16(&dst[dstIdx], &src[srcIdx], &dst[dstIdx - 16]);
360+
srcIdx += 16;
361+
dstIdx += 16;
362+
}
363+
}
364+
else if (dist == 8) {
365+
while ((srcIdx + 8 <= srcEnd) && (dstIdx + 8 <= dstEnd)) {
366+
KANZI_MEM_XOR8(&dst[dstIdx], &src[srcIdx], &dst[dstIdx - 8]);
367+
srcIdx += 8;
368+
dstIdx += 8;
369+
}
370+
}
371+
341372
while ((srcIdx < srcEnd) && (dstIdx < dstEnd)) {
342373
dst[dstIdx] = src[srcIdx] ^ dst[dstIdx - dist];
343374
srcIdx++;

0 commit comments

Comments
 (0)