From: Sebastian Pop Date: Thu, 20 Dec 2018 20:08:16 +0000 (-0600) Subject: fix bug #263: hoist invariant loads X-Git-Tag: 1.9.9-b1~560 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=305a0a265e0935acd8538deb4ff8b8bc36840c1c;p=thirdparty%2Fzlib-ng.git fix bug #263: hoist invariant loads This patch speeds up longest_match when compiled with clang for x86_64 to match the performance of zlib.org. The performance of zlib-ng does not change much when compiled with gcc for x86_64, or when zlib-ng is cross compiled by gcc or llvm for aarch64. Performance analysis for this patch: https://gist.github.com/sebpop/7cdc5b2abd3297c5fcd2a8315bd9a209 --- diff --git a/match.c b/match.c index fd55c3e1..207aedf7 100644 --- a/match.c +++ b/match.c @@ -347,21 +347,23 @@ ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) { */ ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) { + unsigned int strstart = s->strstart; unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register unsigned char *scan = s->window + s->strstart; /* current string */ + unsigned char *window = s->window; + register unsigned char *scan = window + strstart; /* current string */ register unsigned char *match; /* matched string */ register unsigned int len; /* length of current match */ unsigned int best_len = s->prev_length; /* best match length so far */ unsigned int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; + IPos limit = strstart > (IPos)MAX_DIST(s) ? + strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Pos *prev = s->prev; unsigned int wmask = s->w_mask; - register unsigned char *strend = s->window + s->strstart + MAX_MATCH; + register unsigned char *strend = window + strstart + MAX_MATCH; uint16_t scan_start, scan_end; @@ -382,10 +384,10 @@ ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) { */ if ((unsigned int)nice_match > s->lookahead) nice_match = s->lookahead; - Assert((unsigned long)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((unsigned long)strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { - if (cur_match >= s->strstart) { + if (cur_match >= strstart) { break; } @@ -397,10 +399,9 @@ ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) { * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ - unsigned char *win = s->window; int cont = 1; do { - match = win + cur_match; + match = window + cur_match; if (likely(memcmp(match+best_len-1, &scan_end, sizeof(scan_end)) != 0)) { if ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0) { @@ -450,7 +451,7 @@ ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) { if (scan > strend) scan = strend; - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= window + (unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH;