Skip to content

Commit

Permalink
WIP - DO NOT SUBMIT
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 616511383
  • Loading branch information
Brotli authored and copybara-github committed Apr 19, 2024
1 parent 1b3a5cc commit d2851a7
Show file tree
Hide file tree
Showing 6 changed files with 733 additions and 13 deletions.
120 changes: 116 additions & 4 deletions c/common/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
#ifndef BROTLI_COMMON_PLATFORM_H_
#define BROTLI_COMMON_PLATFORM_H_

#include <string.h> /* memcpy */

#include <brotli/port.h>
#include <brotli/types.h>

#include <sys/types.h> /* should include endian.h for us */
#include <immintrin.h>
#include <string.h> /* memcpy */
#include <sys/types.h> /* should include endian.h for us */
#include <stdio.h>

#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
#include <intrin.h>
Expand Down Expand Up @@ -282,6 +282,11 @@ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
memcpy(&t, p, sizeof t);
return t;
}
static BROTLI_INLINE size_t BrotliUnalignedReadSizeT(const void* p) {
size_t t;
memcpy(&t, p, sizeof t);
return t;
}
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
memcpy(p, &v, sizeof v);
}
Expand Down Expand Up @@ -489,6 +494,113 @@ BROTLI_COMMON_API void* BrotliDefaultAllocFunc(void* opaque, size_t size);
/* Default brotli_free_func */
BROTLI_COMMON_API void BrotliDefaultFreeFunc(void* opaque, void* address);

static BROTLI_INLINE uint64_t RotateRightU64(uint64_t const value,
size_t count) {
count &= 0x3F; /* for fickle pattern recognition */
return (value >> count) | (uint64_t)(value << ((0U - count) & 0x3F));
}
static BROTLI_INLINE uint32_t RotateRightU32(uint32_t const value,
size_t count) {
count &= 0x1F; /* for fickle pattern recognition */
return (value >> count) | (uint32_t)(value << ((0U - count) & 0x1F));
}
static BROTLI_INLINE uint16_t RotateRightU16(uint16_t const value,
size_t count) {
count &= 0x0F; /* for fickle pattern recognition */
return (value >> count) | (uint16_t)(value << ((0U - count) & 0x0F));
}
static BROTLI_INLINE uint64_t GetMatchingTagMask(
size_t chunk_count, const uint8_t tag,
const uint8_t* BROTLI_RESTRICT tag_bucket, const size_t head) {
uint64_t matches = 0;
#if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))
const __m128i comparison_mask = _mm_set1_epi8((char)tag);
size_t i;
for (i = 0; i < chunk_count && i < 4; i++) {
const __m128i chunk =
_mm_loadu_si128((const __m128i*)(const void*)(tag_bucket + 16 * i));
const __m128i equal_mask = _mm_cmpeq_epi8(chunk, comparison_mask);
matches |= (uint64_t)_mm_movemask_epi8(equal_mask) << 16 * i;
}
#else
const int chunk_size = sizeof(size_t);
const size_t shift_amount = ((chunk_size * 8) - chunk_size);
const size_t xFF = ~((size_t)0);
const size_t x01 = xFF / 0xFF;
const size_t x80 = x01 << 7;
const size_t splat_char = tag * x01;
int i = ((int)chunk_count * 16) - chunk_size;
BROTLI_DCHECK((sizeof(size_t) == 4) || (sizeof(size_t) == 8));
#if BROTLI_LITTLE_ENDIAN
const size_t extractMagic = (xFF / 0x7F) >> chunk_size;
do {
size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
chunk ^= splat_char;
chunk = (((chunk | x80) - x01) | chunk) & x80;
matches <<= chunk_size;
matches |= (chunk * extractMagic) >> shift_amount;
i -= chunk_size;
} while (i >= 0);
#else
const size_t msb = xFF ^ (xFF >> 1);
const size_t extractMagic = (msb / 0x1FF) | msb;
do {
size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
chunk ^= splat_char;
chunk = (((chunk | x80) - x01) | chunk) & x80;
matches <<= chunk_size;
matches |= ((chunk >> 7) * extractMagic) >> shift_amount;
i -= chunk_size;
} while (i >= 0);
#endif
matches = ~matches;
#endif
if (chunk_count == 1) return RotateRightU16((uint16_t)matches, head);
if (chunk_count == 2) return RotateRightU32((uint32_t)matches, head);
return RotateRightU64(matches, head);
}

// static BROTLI_INLINE uint64_t GetMatchingTagMaskSwar(
// size_t chunk_count, const uint8_t tag,
// const uint8_t* BROTLI_RESTRICT tag_bucket, const size_t head) {
// uint64_t matches = 0;
// const int chunk_size = sizeof(size_t);
// const size_t shift_amount = ((chunk_size * 8) - chunk_size);
// const size_t xFF = ~((size_t)0);
// const size_t x01 = xFF / 0xFF;
// const size_t x80 = x01 << 7;
// const size_t splat_char = tag * x01;
// int i = ((int)chunk_count * 16) - chunk_size;
// BROTLI_DCHECK((sizeof(size_t) == 4) || (sizeof(size_t) == 8));
// if (BROTLI_LITTLE_ENDIAN) { /* runtime check so have two loops */
// const size_t extractMagic = (xFF / 0x7F) >> chunk_size;
// do {
// size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
// chunk ^= splat_char;
// chunk = (((chunk | x80) - x01) | chunk) & x80;
// matches <<= chunk_size;
// matches |= (chunk * extractMagic) >> shift_amount;
// i -= chunk_size;
// } while (i >= 0);
// } else { /* big endian: reverse bits during extraction */
// const size_t msb = xFF ^ (xFF >> 1);
// const size_t extractMagic = (msb / 0x1FF) | msb;
// do {
// size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
// chunk ^= splat_char;
// chunk = (((chunk | x80) - x01) | chunk) & x80;
// matches <<= chunk_size;
// matches |= ((chunk >> 7) * extractMagic) >> shift_amount;
// i -= chunk_size;
// } while (i >= 0);
// }
// matches = ~matches;
// if (chunk_count == 1) return RotateRightU16((uint16_t)matches, head);
// if (chunk_count == 2) return RotateRightU32((uint32_t)matches, head);
// return RotateRightU64(matches, head);
// }


BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
BROTLI_UNUSED(&BrotliSuppressUnusedFunctions);
BROTLI_UNUSED(&BrotliUnalignedRead16);
Expand Down
20 changes: 20 additions & 0 deletions c/enc/backward_references.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,
#include "backward_references_inc.h"
#undef HASHER

#define HASHER() H58
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER

#define HASHER() H68
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER

#undef ENABLE_COMPOUND_DICTIONARY
#undef PREFIX
#define PREFIX() D
Expand Down Expand Up @@ -149,6 +159,14 @@ static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#define HASHER() H58
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#define HASHER() H68
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER

#undef ENABLE_COMPOUND_DICTIONARY
#undef PREFIX
Expand All @@ -174,6 +192,8 @@ void BrotliCreateBackwardReferences(size_t num_bytes,
return;
CASE_(5)
CASE_(6)
CASE_(58)
CASE_(68)
CASE_(40)
CASE_(41)
CASE_(42)
Expand Down
11 changes: 10 additions & 1 deletion c/enc/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
#include "hash_longest_match64_inc.h" /* NOLINT(build/include) */
#undef HASHER

#define HASHER() H58
#include "hash_longest_match_simd_inc.h" /* NOLINT(build/include) */
#undef HASHER

#define HASHER() H68
#include "hash_longest_match64_simd_inc.h" /* NOLINT(build/include) */
#undef HASHER

#define BUCKET_BITS 15

#define NUM_LAST_DISTANCES_TO_CHECK 4
Expand Down Expand Up @@ -388,7 +396,8 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
#undef CAT
#undef EXPAND_CAT

#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
#define FOR_SIMPLE_HASHERS(H) \
H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) H(58) H(68)
#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
Expand Down
Loading

0 comments on commit d2851a7

Please sign in to comment.