| /* slide_hash.c -- slide hash table C implementation |
| * |
| * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler |
| * For conditions of distribution and use, see copyright notice in zlib.h |
| */ |
| |
| #include "zbuild.h" |
| #include "deflate.h" |
| |
| /* =========================================================================== |
| * Slide the hash table when sliding the window down (could be avoided with 32 |
| * bit values at the expense of memory usage). We slide even when level == 0 to |
| * keep the hash table consistent if we switch back to level > 0 later. |
| */ |
| static inline void slide_hash_c_chain(Pos *table, uint32_t entries, uint16_t wsize) { |
| #ifdef NOT_TWEAK_COMPILER |
| table += entries; |
| do { |
| unsigned m; |
| m = *--table; |
| *table = (Pos)(m >= wsize ? m-wsize : 0); |
| /* If entries is not on any hash chain, prev[entries] is garbage but |
| * its value will never be used. |
| */ |
| } while (--entries); |
| #else |
| { |
| /* As of I make this change, gcc (4.8.*) isn't able to vectorize |
| * this hot loop using saturated-subtraction on x86-64 architecture. |
| * To avoid this defect, we can change the loop such that |
| * o. the pointer advance forward, and |
| * o. demote the variable 'm' to be local to the loop, and |
| * choose type "Pos" (instead of 'unsigned int') for the |
| * variable to avoid unnecessary zero-extension. |
| */ |
| unsigned int i; |
| Pos *q = table; |
| for (i = 0; i < entries; i++) { |
| Pos m = *q; |
| Pos t = (Pos)wsize; |
| *q++ = (Pos)(m >= t ? m-t: 0); |
| } |
| } |
| #endif /* NOT_TWEAK_COMPILER */ |
| } |
| |
| Z_INTERNAL void slide_hash_c(deflate_state *s) { |
| unsigned int wsize = s->w_size; |
| |
| slide_hash_c_chain(s->head, HASH_SIZE, wsize); |
| slide_hash_c_chain(s->prev, wsize, wsize); |
| } |