diff options
| author | Markus F.X.J. Oberhumer <markus@oberhumer.com> | 2012-08-13 11:25:44 -0400 |
|---|---|---|
| committer | Markus F.X.J. Oberhumer <markus@oberhumer.com> | 2013-02-20 13:36:01 -0500 |
| commit | 8b975bd3f9089f8ee5d7bbfd798537b992bbc7e7 (patch) | |
| tree | 09078bdf5e805a5f921d8b7b592262ef3e877937 /lib | |
| parent | b6bec26cea948148a9420e7a0ac337f925de49e7 (diff) | |
lib/lzo: Update LZO compression to current upstream version
This commit updates the kernel LZO code to the current upsteam version
which features a significant speed improvement - benchmarking the Calgary
and Silesia test corpora typically shows a doubled performance in
both compression and decompression on modern i386/x86_64/powerpc machines.
Signed-off-by: Markus F.X.J. Oberhumer <markus@oberhumer.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/lzo/lzo1x_compress.c | 335 | ||||
| -rw-r--r-- | lib/lzo/lzo1x_decompress_safe.c | 350 | ||||
| -rw-r--r-- | lib/lzo/lzodefs.h | 38 |
3 files changed, 387 insertions, 336 deletions
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c index a6040990a62e..236eb21167b5 100644 --- a/lib/lzo/lzo1x_compress.c +++ b/lib/lzo/lzo1x_compress.c | |||
| @@ -1,194 +1,243 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * LZO1X Compressor from MiniLZO | 2 | * LZO1X Compressor from LZO |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com> | 4 | * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> |
| 5 | * | 5 | * |
| 6 | * The full LZO package can be found at: | 6 | * The full LZO package can be found at: |
| 7 | * http://www.oberhumer.com/opensource/lzo/ | 7 | * http://www.oberhumer.com/opensource/lzo/ |
| 8 | * | 8 | * |
| 9 | * Changed for kernel use by: | 9 | * Changed for Linux kernel use by: |
| 10 | * Nitin Gupta <nitingupta910@gmail.com> | 10 | * Nitin Gupta <nitingupta910@gmail.com> |
| 11 | * Richard Purdie <rpurdie@openedhand.com> | 11 | * Richard Purdie <rpurdie@openedhand.com> |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/lzo.h> | ||
| 17 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
| 17 | #include <linux/lzo.h> | ||
| 18 | #include "lzodefs.h" | 18 | #include "lzodefs.h" |
| 19 | 19 | ||
| 20 | static noinline size_t | 20 | static noinline size_t |
| 21 | _lzo1x_1_do_compress(const unsigned char *in, size_t in_len, | 21 | lzo1x_1_do_compress(const unsigned char *in, size_t in_len, |
| 22 | unsigned char *out, size_t *out_len, void *wrkmem) | 22 | unsigned char *out, size_t *out_len, |
| 23 | size_t ti, void *wrkmem) | ||
| 23 | { | 24 | { |
| 25 | const unsigned char *ip; | ||
| 26 | unsigned char *op; | ||
| 24 | const unsigned char * const in_end = in + in_len; | 27 | const unsigned char * const in_end = in + in_len; |
| 25 | const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5; | 28 | const unsigned char * const ip_end = in + in_len - 20; |
| 26 | const unsigned char ** const dict = wrkmem; | 29 | const unsigned char *ii; |
| 27 | const unsigned char *ip = in, *ii = ip; | 30 | lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; |
| 28 | const unsigned char *end, *m, *m_pos; | ||
| 29 | size_t m_off, m_len, dindex; | ||
| 30 | unsigned char *op = out; | ||
| 31 | 31 | ||
| 32 | ip += 4; | 32 | op = out; |
| 33 | ip = in; | ||
| 34 | ii = ip; | ||
| 35 | ip += ti < 4 ? 4 - ti : 0; | ||
| 33 | 36 | ||
| 34 | for (;;) { | 37 | for (;;) { |
| 35 | dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK; | 38 | const unsigned char *m_pos; |
| 36 | m_pos = dict[dindex]; | 39 | size_t t, m_len, m_off; |
| 37 | 40 | u32 dv; | |
| 38 | if (m_pos < in) | ||
| 39 | goto literal; | ||
| 40 | |||
| 41 | if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) | ||
| 42 | goto literal; | ||
| 43 | |||
| 44 | m_off = ip - m_pos; | ||
| 45 | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) | ||
| 46 | goto try_match; | ||
| 47 | |||
| 48 | dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f); | ||
| 49 | m_pos = dict[dindex]; | ||
| 50 | |||
| 51 | if (m_pos < in) | ||
| 52 | goto literal; | ||
| 53 | |||
| 54 | if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) | ||
| 55 | goto literal; | ||
| 56 | |||
| 57 | m_off = ip - m_pos; | ||
| 58 | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) | ||
| 59 | goto try_match; | ||
| 60 | |||
| 61 | goto literal; | ||
| 62 | |||
| 63 | try_match: | ||
| 64 | if (get_unaligned((const unsigned short *)m_pos) | ||
| 65 | == get_unaligned((const unsigned short *)ip)) { | ||
| 66 | if (likely(m_pos[2] == ip[2])) | ||
| 67 | goto match; | ||
| 68 | } | ||
| 69 | |||
| 70 | literal: | 41 | literal: |
| 71 | dict[dindex] = ip; | 42 | ip += 1 + ((ip - ii) >> 5); |
| 72 | ++ip; | 43 | next: |
| 73 | if (unlikely(ip >= ip_end)) | 44 | if (unlikely(ip >= ip_end)) |
| 74 | break; | 45 | break; |
| 75 | continue; | 46 | dv = get_unaligned_le32(ip); |
| 76 | 47 | t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK; | |
| 77 | match: | 48 | m_pos = in + dict[t]; |
| 78 | dict[dindex] = ip; | 49 | dict[t] = (lzo_dict_t) (ip - in); |
| 79 | if (ip != ii) { | 50 | if (unlikely(dv != get_unaligned_le32(m_pos))) |
| 80 | size_t t = ip - ii; | 51 | goto literal; |
| 81 | 52 | ||
| 53 | ii -= ti; | ||
| 54 | ti = 0; | ||
| 55 | t = ip - ii; | ||
| 56 | if (t != 0) { | ||
| 82 | if (t <= 3) { | 57 | if (t <= 3) { |
| 83 | op[-2] |= t; | 58 | op[-2] |= t; |
| 84 | } else if (t <= 18) { | 59 | COPY4(op, ii); |
| 60 | op += t; | ||
| 61 | } else if (t <= 16) { | ||
| 85 | *op++ = (t - 3); | 62 | *op++ = (t - 3); |
| 63 | COPY8(op, ii); | ||
| 64 | COPY8(op + 8, ii + 8); | ||
| 65 | op += t; | ||
| 86 | } else { | 66 | } else { |
| 87 | size_t tt = t - 18; | 67 | if (t <= 18) { |
| 88 | 68 | *op++ = (t - 3); | |
| 89 | *op++ = 0; | 69 | } else { |
| 90 | while (tt > 255) { | 70 | size_t tt = t - 18; |
| 91 | tt -= 255; | ||
| 92 | *op++ = 0; | 71 | *op++ = 0; |
| 72 | while (unlikely(tt > 255)) { | ||
| 73 | tt -= 255; | ||
| 74 | *op++ = 0; | ||
| 75 | } | ||
| 76 | *op++ = tt; | ||
| 93 | } | 77 | } |
| 94 | *op++ = tt; | 78 | do { |
| 79 | COPY8(op, ii); | ||
| 80 | COPY8(op + 8, ii + 8); | ||
| 81 | op += 16; | ||
| 82 | ii += 16; | ||
| 83 | t -= 16; | ||
| 84 | } while (t >= 16); | ||
| 85 | if (t > 0) do { | ||
| 86 | *op++ = *ii++; | ||
| 87 | } while (--t > 0); | ||
| 95 | } | 88 | } |
| 96 | do { | ||
| 97 | *op++ = *ii++; | ||
| 98 | } while (--t > 0); | ||
| 99 | } | 89 | } |
| 100 | 90 | ||
| 101 | ip += 3; | 91 | m_len = 4; |
| 102 | if (m_pos[3] != *ip++ || m_pos[4] != *ip++ | 92 | { |
| 103 | || m_pos[5] != *ip++ || m_pos[6] != *ip++ | 93 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64) |
| 104 | || m_pos[7] != *ip++ || m_pos[8] != *ip++) { | 94 | u64 v; |
| 105 | --ip; | 95 | v = get_unaligned((const u64 *) (ip + m_len)) ^ |
| 106 | m_len = ip - ii; | 96 | get_unaligned((const u64 *) (m_pos + m_len)); |
| 97 | if (unlikely(v == 0)) { | ||
| 98 | do { | ||
| 99 | m_len += 8; | ||
| 100 | v = get_unaligned((const u64 *) (ip + m_len)) ^ | ||
| 101 | get_unaligned((const u64 *) (m_pos + m_len)); | ||
| 102 | if (unlikely(ip + m_len >= ip_end)) | ||
| 103 | goto m_len_done; | ||
| 104 | } while (v == 0); | ||
| 105 | } | ||
| 106 | # if defined(__LITTLE_ENDIAN) | ||
| 107 | m_len += (unsigned) __builtin_ctzll(v) / 8; | ||
| 108 | # elif defined(__BIG_ENDIAN) | ||
