From: Nathan Moinvaziri Date: Mon, 8 Dec 2025 03:59:36 +0000 (-0800) Subject: Compute w_bits rather than storing it in the deflate_state structure X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9aeb4aa2a811ee1eb0e5f827e3d3f29da4ad62a;p=thirdparty%2Fzlib-ng.git Compute w_bits rather than storing it in the deflate_state structure Co-authored-by: Brian Pane --- diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index f602b44be..8ec3146cb 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -60,7 +60,7 @@ static inline int dfltcc_can_deflate_with_params(PREFIX3(streamp) strm, int leve int Z_INTERNAL PREFIX(dfltcc_can_deflate)(PREFIX3(streamp) strm) { deflate_state *state = (deflate_state *)strm->state; - return dfltcc_can_deflate_with_params(strm, state->level, state->w_bits, state->strategy, state->reproducible); + return dfltcc_can_deflate_with_params(strm, state->level, W_BITS(state), state->strategy, state->reproducible); } static inline void dfltcc_gdht(PREFIX3(streamp) strm) { @@ -319,7 +319,7 @@ static int dfltcc_was_deflate_used(PREFIX3(streamp) strm) { int Z_INTERNAL PREFIX(dfltcc_deflate_params)(PREFIX3(streamp) strm, int level, int strategy, int *flush) { deflate_state *state = (deflate_state *)strm->state; int could_deflate = PREFIX(dfltcc_can_deflate)(strm); - int can_deflate = dfltcc_can_deflate_with_params(strm, level, state->w_bits, strategy, state->reproducible); + int can_deflate = dfltcc_can_deflate_with_params(strm, level, W_BITS(state), strategy, state->reproducible); if (can_deflate == could_deflate) /* We continue to work in the same mode - no changes needed */ diff --git a/deflate.c b/deflate.c index 1002fa6eb..8aa693551 100644 --- a/deflate.c +++ b/deflate.c @@ -302,8 +302,7 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level s->wrap = wrap; s->gzhead = NULL; - s->w_bits = (unsigned int)windowBits; - s->w_size = 1 << s->w_bits; + s->w_size = 1 << windowBits; s->high_water = 0; /* nothing written to s->window yet */ @@ -724,7 +723,7 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long /* if not default parameters, return conservative bound */ if (DEFLATE_NEED_CONSERVATIVE_BOUND(strm) || /* hook for IBM Z DFLTCC */ - s->w_bits != MAX_WBITS || HASH_BITS < 15) { + W_BITS(s) != MAX_WBITS || HASH_BITS < 15) { if (s->level == 0) { /* upper bound for stored blocks with length 127 (memLevel == 1) -- ~4% overhead plus a small constant */ @@ -814,7 +813,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ - unsigned int header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + unsigned int header = (Z_DEFLATED + ((W_BITS(s)-8)<<4)) << 8; unsigned int level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) @@ -1086,7 +1085,7 @@ int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); - deflate_allocs *alloc_bufs = alloc_deflate(dest, ss->w_bits, ss->lit_bufsize); + deflate_allocs *alloc_bufs = alloc_deflate(dest, W_BITS(ss), ss->lit_bufsize); if (alloc_bufs == NULL) return Z_MEM_ERROR; diff --git a/deflate.h b/deflate.h index 9cd0fe8f6..fb6f7cd1e 100644 --- a/deflate.h +++ b/deflate.h @@ -155,7 +155,6 @@ struct ALIGNED_(64) internal_state { /* used by deflate.c: */ unsigned int w_size; /* LZ77 window size (32K by default) */ - unsigned int w_bits; /* log2(w_size) (8..16) */ unsigned int lookahead; /* number of valid bytes ahead in window */ unsigned int high_water; @@ -406,6 +405,29 @@ static inline void put_uint64(deflate_state *s, uint64_t lld) { #define W_MASK(s) ((s)->w_size - 1) /* Window mask: w_size is always a power of 2, so w_mask = w_size - 1 */ +#ifdef HAVE_BUILTIN_CTZ +# define W_BITS(s) ((unsigned int)__builtin_ctz((s)->w_size)) +#else +/* Fallback for w_size which is always a power of 2 between 256 and 32768 */ +static inline unsigned int compute_w_bits(unsigned int w_size) { + /* Switch ordered by likelihood - most common first (MAX_WBITS=15 -> 32768) */ + switch (w_size) { + case 32768: return 15; /* MAX_WBITS default */ + case 16384: return 14; + case 8192: return 13; + case 4096: return 12; + case 2048: return 11; + case 1024: return 10; + case 512: return 9; + case 256: return 8; + } + Assert(w_size >= 256 && w_size <= 32768, "invalid w_size"); + return 0; +} +# define W_BITS(s) compute_w_bits((s)->w_size) +#endif +/* Window bits: log2(w_size), computed from w_size since w_size is a power of 2 */ + #define WIN_INIT STD_MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ diff --git a/test/benchmarks/benchmark_insert_string.cc b/test/benchmarks/benchmark_insert_string.cc index 7a68fb519..a793b795d 100644 --- a/test/benchmarks/benchmark_insert_string.cc +++ b/test/benchmarks/benchmark_insert_string.cc @@ -34,7 +34,6 @@ public: // Set up window parameters s->w_size = MAX_WSIZE; - s->w_bits = 15; s->window_size = TEST_WINDOW_SIZE; // Allocate window