- New cmake file, by Nobuhiro Iwamatsu, which can also produce shared and static...
authoryann.collet.73@gmail.com <yann.collet.73@gmail.com@650e7d94-2a16-8b24-b05c-7c0b3f6821cd>
Sat, 2 Mar 2013 23:34:21 +0000 (23:34 +0000)
committeryann.collet.73@gmail.com <yann.collet.73@gmail.com@650e7d94-2a16-8b24-b05c-7c0b3f6821cd>
Sat, 2 Mar 2013 23:34:21 +0000 (23:34 +0000)
- Improved decoding speed, even more for 64-bits, and "safe" version
- Slight speed increase for LZ4-HC
- Pushed a useless parameter down the list in lz4.c

git-svn-id: https://lz4.googlecode.com/svn/trunk@90 650e7d94-2a16-8b24-b05c-7c0b3f6821cd

bench.c
cmake/CMakeLists.txt
cmake/release_COPYING.txt [new file with mode: 0644]
fuzzer.c
lz4.c
lz4hc.c

diff --git a/bench.c b/bench.c
index 2758007..d185811 100644 (file)
--- a/bench.c
+++ b/bench.c
@@ -433,7 +433,8 @@ int BMK_benchFile(char** fileNamesTable, int nbFiles, int cLevel)
                  while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
                  {\r
                        for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
-                               chunkP[chunkNb].outputSize = compP.decompressionFunction(chunkP[chunkNb].outputBuffer, chunkP[chunkNb].inputBuffer, chunkP[chunkNb].inputSize);\r
+                               chunkP[chunkNb].outputSize = LZ4_uncompress(chunkP[chunkNb].outputBuffer, chunkP[chunkNb].inputBuffer, chunkP[chunkNb].inputSize);\r
+                               //chunkP[chunkNb].inputSize = LZ4_uncompress_unknownOutputSize(chunkP[chunkNb].outputBuffer, chunkP[chunkNb].inputBuffer, chunkP[chunkNb].outputSize, chunkSize);\r
                        nb_loops++;\r
                  }\r
                  milliTime = BMK_GetMilliSpan(milliTime);\r
index a406fc8..62bc347 100644 (file)
@@ -4,7 +4,7 @@ set(CPACK_PACKAGE_VERSION_MAJOR 0)
 set(CPACK_PACKAGE_VERSION_MINOR 0)\r
 set(CPACK_PACKAGE_VERSION_PATCH r51)\r
 #set(CPACK_RESOURCE_FILE_LICENSE  ${CMAKE_CURRENT_BINARY_DIR}/COPYING_LGPL)\r
-                                  set(VERSION_STRING   " \"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\" ")\r
+set(VERSION_STRING     " \"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\" ")\r
 include(CPack)\r
 \r
 \r
@@ -16,25 +16,75 @@ IF( ${SIZEOF_VOID_P} STREQUAL  "8" )
     MESSAGE( STATUS "64 bit architecture detected size of void * is " ${SIZEOF_VOID_P})\r
 ENDIF()\r
 \r
+set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries")\r
+\r
+if (BUILD_SHARED_LIBS)\r
+    message(STATUS "Enable shared library building")\r
+else(BUILD_SHARED_LIBS)\r
+    message(STATUS "Disable shared library building")\r
+endif(BUILD_SHARED_LIBS)\r
+\r
+if(UNIX AND BUILD_SHARED_LIBS)\r
+    if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")\r
+        add_definitions(-fPIC)\r
+    endif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")\r
+endif()\r
 \r
 set(SRC_DIR ../)\r
 set(LZ4_SRCS_LIB ${SRC_DIR}lz4.c ${SRC_DIR}lz4hc.c ${SRC_DIR}lz4.h )\r
-set(LZ4_SRCS ${LZ4_SRCS_LIB} ${SRC_DIR}bench.c ${SRC_DIR}lz4demo.c )\r
+set(LZ4_SRCS ${SRC_DIR}bench.c ${SRC_DIR}lz4demo.c)\r
 \r
-# EXECUTABLES FOR 32 Bit and 64 versions\r
-if(CMAKE_SYSTEM_PROCESSOR STREQUAL "64bit")\r
-       add_executable(lz4demo64 ${LZ4_SRCS})\r
-        install(TARGETS lz4demo64 RUNTIME DESTINATION "./")\r
+if(NOT BUILD_SHARED_LIBS)\r
+    set(LZ4_SRCS ${LZ4_SRCS} ${LZ4_SRCS_LIB})\r
 endif()\r
 \r
-       add_executable(lz4demo32 ${LZ4_SRCS})\r
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "64bit")\r
+    message(STATUS "Build 64bit executable binary")\r
+    add_executable(lz4demo64 ${LZ4_SRCS})\r
+    install(TARGETS lz4demo64 RUNTIME DESTINATION "./")\r
+    if(NOT BUILD_SHARED_LIBS)\r
+        message(STATUS "Build 32bit executable binary")\r
+        add_executable(lz4demo32 ${LZ4_SRCS})\r
         install(TARGETS lz4demo32 RUNTIME DESTINATION "./")\r
 \r
-if(CMAKE_SYSTEM_PROCESSOR STREQUAL "64bit")\r
-SET_TARGET_PROPERTIES(lz4demo32 PROPERTIES\r
-       COMPILE_FLAGS PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")\r
+        SET_TARGET_PROPERTIES(lz4demo32 PROPERTIES\r
+            COMPILE_FLAGS PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")\r
+    endif()\r
+else()\r
+    message(STATUS "Build 32bit executable binary")\r
+    add_executable(lz4demo32 ${LZ4_SRCS})\r
+    install(TARGETS lz4demo32 RUNTIME DESTINATION "./")\r
 endif()\r
 \r
+if(BUILD_SHARED_LIBS)\r
+    set(LZ4_SOVERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")\r
+    if (CMAKE_SYSTEM_PROCESSOR STREQUAL "64bit")\r
+        target_link_libraries(lz4demo64 liblz4)\r
+    else()\r
+        target_link_libraries(lz4demo32 liblz4)\r
+    endif()\r
+       \r
+    # for static library\r
+    add_library(liblz4_static STATIC ${LZ4_SRCS_LIB})\r
+    set_target_properties(liblz4_static PROPERTIES OUTPUT_NAME lz4)\r
+\r
+    install(TARGETS liblz4_static\r
+        LIBRARY DESTINATION lib\r
+        ARCHIVE DESTINATION lib\r
+    )\r
+\r
+    # for shared library o\r
+    add_library(liblz4 ${LZ4_SRCS_LIB})\r
+    set_target_properties(liblz4 PROPERTIES\r
+            OUTPUT_NAME lz4\r
+            SOVERSION ${LZ4_SOVERSION})\r
+\r
+    install(TARGETS liblz4\r
+        LIBRARY DESTINATION lib\r
+        ARCHIVE DESTINATION lib\r
+    )\r
+endif(BUILD_SHARED_LIBS)\r
+\r
 \r
 #warnings\r
 \r
@@ -47,6 +97,4 @@ ADD_DEFINITIONS("-Os -march=native -std=c99")
 INCLUDE_DIRECTORIES (${SRC_DIR})\r
 \r
 \r
-#target_link_libraries(lz4 ${LZ4_SRCS_LIB})\r
-\r
 \r
diff --git a/cmake/release_COPYING.txt b/cmake/release_COPYING.txt
new file mode 100644 (file)
index 0000000..32cec0d
--- /dev/null
@@ -0,0 +1,21 @@
+\r
+    lz4demo and fuzzer is an open-source demo compression algorithm LZ4 programs\r
+    Copyright (C) Yann Collet 2012\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License along\r
+    with this program; if not, write to the Free Software Foundation, Inc.,\r
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+\r
+       You can contact the author at :\r
+       - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\r
+       - LZ4 source repository : http://code.google.com/p/lz4/\r
index a5f9e2b..11697fd 100644 (file)
--- a/fuzzer.c
+++ b/fuzzer.c
@@ -144,7 +144,8 @@ int main() {
                for (i = 0; i < 2048; i++)\r
                 cbuf[FUZ_avail + i] = cbuf[FUZ_avail + 2048 + i] = FUZ_rand(&seed) >> 16;\r
 \r
-        for (i = 0; i < NB_ATTEMPTS; i++) {\r
+        for (i = 0; i < NB_ATTEMPTS; i++) \r
+        {\r
                        printf("\r%7i /%7i\r", i, NB_ATTEMPTS);\r
                        \r
                        FUZ_rand(&seed);\r
@@ -171,7 +172,7 @@ int main() {
 \r
                        // Test decoding with output size being exactly what's necessary => must work\r
                        ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN);\r
-                       if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }\r
+                       if (ret<0) { printf("decompression failed despite correct space: seed %u, len %d\n", seed, LEN); goto _output_error; }\r
 \r
                        // Test decoding with one byte missing => must fail\r
                        ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN-1);\r
@@ -185,7 +186,7 @@ int main() {
                        ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN+1);\r
                        if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }\r
 \r
-                       // Test decoding with output size being exactly what's necessary => should work\r
+                       // Test decoding with output size being exactly what's necessary => must work\r
                        ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN);\r
                        if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }\r
 \r
diff --git a/lz4.c b/lz4.c
index a35f12b..1f2eafd 100644 (file)
--- a/lz4.c
+++ b/lz4.c
 // Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache\r
 #define MEMORY_USAGE 14\r
 \r
-// NOTCOMPRESSIBLE_DETECTIONLEVEL :\r
-// Decreasing this value will make the algorithm skip faster data segments considered "incompressible"\r
-// This may decrease compression ratio dramatically, but will be faster on incompressible data\r
-// Increasing this value will make the algorithm search more before declaring a segment "incompressible"\r
-// This could improve compression a bit, but will be slower on incompressible data\r
-// The default value (6) is recommended\r
-#define NOTCOMPRESSIBLE_DETECTIONLEVEL 6\r
-\r
 // BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE :\r
 // This will provide a small boost to performance for big endian cpu, but the resulting compressed stream will be incompatible with little-endian CPU.\r
 // You can set this option to 1 in situations where data will remain within closed environment\r
@@ -188,6 +180,13 @@ typedef struct _U64_S { U64 v; } U64_S;
 #define HASHTABLESIZE (1 << HASH_LOG)\r
 #define HASH_MASK (HASHTABLESIZE - 1)\r
 \r
+// NOTCOMPRESSIBLE_DETECTIONLEVEL :\r
+// Decreasing this value will make the algorithm skip faster data segments considered "incompressible"\r
+// This may decrease compression ratio dramatically, but will be faster on incompressible data\r
+// Increasing this value will make the algorithm search more before declaring a segment "incompressible"\r
+// This could improve compression a bit, but will be slower on incompressible data\r
+// The default value (6) is recommended\r
+#define NOTCOMPRESSIBLE_DETECTIONLEVEL 6\r
 #define SKIPSTRENGTH (NOTCOMPRESSIBLE_DETECTIONLEVEL>2?NOTCOMPRESSIBLE_DETECTIONLEVEL:2)\r
 #define STACKLIMIT 13\r
 #define HEAPMODE (HASH_LOG>STACKLIMIT)  // Defines if memory is allocated into the stack (local variable), or into the heap (malloc()).\r
@@ -309,7 +308,7 @@ static inline int LZ4_NbCommonBytes (register U32 val)
     #endif\r
 #else\r
     #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
-    unsigned long r = 0;\r
+    unsigned long r;\r
     _BitScanForward( &r, val );\r
     return (int)(r>>3);\r
     #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
@@ -358,7 +357,7 @@ static inline int LZ4_compressCtx(void** ctx,
     BYTE* op = (BYTE*) dest;\r
     BYTE* const oend = op + maxOutputSize;\r
 \r
-    int len, length;\r
+    int length;\r
     const int skipStrength = SKIPSTRENGTH;\r
     U32 forwardH;\r
 \r
@@ -430,7 +429,14 @@ static inline int LZ4_compressCtx(void** ctx,
         }\r
         else *token = (length<<ML_BITS);\r
 #else\r
-        if (length>=(int)RUN_MASK) { *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *op++ = 255; *op++ = (BYTE)len; }\r
+        if (length>=(int)RUN_MASK) \r
+        { \r
+            int len;\r
+            *token=(RUN_MASK<<ML_BITS); \r
+            len = length-RUN_MASK; \r
+            for(; len > 254 ; len-=255) *op++ = 255; \r
+            *op++ = (BYTE)len; \r
+        }\r
         else *token = (length<<ML_BITS);\r
 #endif\r
 \r
@@ -442,7 +448,7 @@ _next_match:
         LZ4_WRITE_LITTLEENDIAN_16(op,(U16)(ip-ref));\r
 \r
         // Start Counting\r
-        ip+=MINMATCH; ref+=MINMATCH;   // MinMatch verified\r
+        ip+=MINMATCH; ref+=MINMATCH;    // MinMatch already verified\r
         anchor = ip;\r
         while likely(ip<matchlimit-(STEPSIZE-1))\r
         {\r
@@ -457,10 +463,17 @@ _next_match:
 _endCount:\r
 \r
         // Encode MatchLength\r
-        len = (int)(ip - anchor);\r
-        if unlikely(op + (1 + LASTLITERALS) + (len>>8) > oend) return 0;               // Check output limit\r
-        if (len>=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *op++ = 255; *op++ = 255; } if (len > 254) { len-=255; *op++ = 255; } *op++ = (BYTE)len; }\r
-        else *token += len;\r
+        length = (int)(ip - anchor);\r
+        if unlikely(op + (1 + LASTLITERALS) + (length>>8) > oend) return 0;            // Check output limit\r
+        if (length>=(int)ML_MASK) \r
+        { \r
+            *token += ML_MASK; \r
+            length -= ML_MASK; \r
+            for (; length > 509 ; length-=510) { *op++ = 255; *op++ = 255; } \r
+            if (length > 254) { length-=255; *op++ = 255; } \r
+            *op++ = (BYTE)length; \r
+        }\r
+        else *token += length;\r
 \r
         // Test end of chunk\r
         if (ip > mflimit) { anchor = ip;  break; }\r
@@ -713,7 +726,6 @@ int LZ4_uncompress(const char* source,
 \r
     unsigned token;\r
 \r
-    size_t length;\r
     size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};\r
 #if LZ4_ARCH64\r
     size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};\r
@@ -723,13 +735,15 @@ int LZ4_uncompress(const char* source,
     // Main Loop\r
     while (1)\r
     {\r
+        size_t length;\r
+\r
         // get runlength\r
         token = *ip++;\r
         if ((length=(token>>ML_BITS)) == RUN_MASK)  { size_t len; for (;(len=*ip++)==255;length+=255){} length += len; }\r
 \r
         // copy literals\r
         cpy = op+length;\r
-        if unlikely(cpy>oend-COPYLENGTH)\r
+        if (cpy>oend-COPYLENGTH)\r
         {\r
             if (cpy != oend) goto _output_error;         // Error : not enough place for another match (min 4) + 5 literals\r
             memcpy(op, ip, length);\r
@@ -740,7 +754,7 @@ int LZ4_uncompress(const char* source,
 \r
         // get offset\r
         LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2;\r
-        if unlikely(ref < (BYTE* const)dest) goto _output_error;   // Error : offset create reference outside destination buffer\r
+        if unlikely(ref < (BYTE* const)dest) goto _output_error;   // Error : offset outside destination buffer\r
 \r
         // get matchlength\r
         if ((length=(token&ML_MASK)) == ML_MASK) { for (;*ip==255;length+=255) {ip++;} length += *ip++; }\r
@@ -762,16 +776,17 @@ int LZ4_uncompress(const char* source,
             op += STEPSIZE-4; ref -= dec64;\r
         } else { LZ4_COPYSTEP(ref,op); }\r
         cpy = op + length - (STEPSIZE-4);\r
-        if (cpy>oend-COPYLENGTH)\r
+\r
+        if unlikely(cpy>oend-(COPYLENGTH)-(STEPSIZE-4))\r
         {\r
-            if (cpy > oend) goto _output_error;             // Error : request to write beyond destination buffer\r
+            if (cpy > oend-LASTLITERALS) goto _output_error;    // Error : last 5 bytes must be literals\r
             LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH));\r
             while(op<cpy) *op++=*ref++;\r
             op=cpy;\r
-            if (op == oend) goto _output_error;    // Check EOF (should never happen, since last 5 bytes are supposed to be literals)\r
             continue;\r
         }\r
-        LZ4_SECURECOPY(ref, op, cpy);\r
+        \r
+        LZ4_WILDCOPY(ref, op, cpy);\r
         op=cpy;                // correction\r
     }\r
 \r
@@ -805,22 +820,29 @@ int LZ4_uncompress_unknownOutputSize(
 #endif\r
 \r
 \r
+    // Special case\r
+    if unlikely(ip==iend) goto _output_error;    // A correctly formed null-compressed LZ4 must have at least one byte (token=0)\r
+\r
     // Main Loop\r
-    while (ip<iend)\r
+    while (1) \r
     {\r
         unsigned token;\r
         size_t length;\r
 \r
         // get runlength\r
         token = *ip++;\r
-        if ((length=(token>>ML_BITS)) == RUN_MASK) { int s=255; while ((ip<iend) && (s==255)) { s=*ip++; length += s; } }\r
+        if ((length=(token>>ML_BITS)) == RUN_MASK) \r
+        { \r
+            int s=255; \r
+            while (likely(ip<iend) && (s==255)) { s=*ip++; length += s; } \r
+        }\r
 \r
         // copy literals\r
         cpy = op+length;\r
-        if ((cpy>oend-COPYLENGTH) || (ip+length>iend-COPYLENGTH))\r
+        if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS)))\r
         {\r
             if (cpy > oend) goto _output_error;          // Error : writes beyond output buffer\r
-            if (ip+length != iend) goto _output_error;   // Error : LZ4 format requires to consume all input at this stage\r
+            if (ip+length != iend) goto _output_error;   // Error : LZ4 format requires to consume all input at this stage (no match within the last 11 bytes, and at least 8 remaining input bytes for another match+literals)\r
             memcpy(op, ip, length);\r
             op += length;\r
             break;                                       // Necessarily EOF, due to parsing restrictions\r
@@ -829,10 +851,19 @@ int LZ4_uncompress_unknownOutputSize(
 \r
         // get offset\r
         LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2;\r
-        if (ref < (BYTE* const)dest) goto _output_error;   // Error : offset creates reference outside of destination buffer\r
+        if unlikely(ref < (BYTE* const)dest) goto _output_error;   // Error : offset outside of destination buffer\r
 \r
         // get matchlength\r
-        if ((length=(token&ML_MASK)) == ML_MASK) { while (ip<iend) { int s = *ip++; length +=s; if (s==255) continue; break; } }\r
+        if ((length=(token&ML_MASK)) == ML_MASK)    \r
+        { \r
+            while likely(ip<iend-(LASTLITERALS+1))    // Error : a minimum input bytes must remain for LASTLITERALS + token\r
+            { \r
+                int s = *ip++; \r
+                length +=s; \r
+                if (s==255) continue; \r
+                break; \r
+            } \r
+        }\r
 \r
         // copy repeated sequence\r
         if unlikely(op-ref<STEPSIZE)\r
@@ -851,16 +882,17 @@ int LZ4_uncompress_unknownOutputSize(
             op += STEPSIZE-4; ref -= dec64;\r
         } else { LZ4_COPYSTEP(ref,op); }\r
         cpy = op + length - (STEPSIZE-4);\r
-        if (cpy>oend-COPYLENGTH)\r
+\r
+        if unlikely(cpy>oend-(COPYLENGTH+(STEPSIZE-4)))\r
         {\r
-            if (cpy > oend) goto _output_error;    // Error : request to write outside of destination buffer\r
+            if (cpy > oend-LASTLITERALS) goto _output_error;    // Error : last 5 bytes must be literals\r
             LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH));\r
             while(op<cpy) *op++=*ref++;\r
             op=cpy;\r
-            if (op == oend) goto _output_error;    // Check EOF (should never happen, since last 5 bytes are supposed to be literals)\r
             continue;\r
         }\r
-        LZ4_SECURECOPY(ref, op, cpy);\r
+\r
+        LZ4_WILDCOPY(ref, op, cpy);\r
         op=cpy;                // correction\r
     }\r
 \r
diff --git a/lz4hc.c b/lz4hc.c
index 341a010..7324492 100644 (file)
--- a/lz4hc.c
+++ b/lz4hc.c
@@ -377,41 +377,29 @@ forceinline static int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4,
     const BYTE* ref;\r
     INITBASE(base,hc4->base);\r
     int nbAttempts=MAX_NB_ATTEMPTS;\r
-    size_t ml=0;\r
+    size_t repl=0, ml=0;\r
+    U16 delta;\r
 \r
     // HC4 match finder\r
     LZ4HC_Insert(hc4, ip);\r
     ref = HASH_POINTER(ip);\r
 \r
-#if 1\r
+#define REPEAT_OPTIMIZATION\r
+#ifdef REPEAT_OPTIMIZATION\r
+    // Detect repetitive sequences of length <= 4\r
     if (ref >= ip-4)               // potential repetition\r
     {\r
         if (A32(ref) == A32(ip))   // confirmed\r
         {\r
-            const U16 delta = (U16)(ip-ref);\r
-            const BYTE* ptr = ip;\r
-            const BYTE* end;\r
-            ml  = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;\r
-            end = ip + ml - (MINMATCH-1);\r
-            while(ptr < end-delta)\r
-            {\r
-                DELTANEXT(ptr) = delta;    // Pre-Load\r
-                ptr++;\r
-            }\r
-            do\r
-            {\r
-                DELTANEXT(ptr) = delta;    \r
-                HashTable[HASH_VALUE(ptr)] = (ptr) - base;     // Head of chain\r
-                ptr++;\r
-            } while(ptr < end);\r
-            hc4->nextToUpdate = end;\r
+            delta = (U16)(ip-ref);\r
+            repl = ml  = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;\r
             *matchpos = ref;\r
         }\r
         ref = GETNEXT(ref);\r
     }\r
 #endif\r
 \r
-    while ((ref >= ip-MAX_DISTANCE) && (ref >= hc4->base) && (nbAttempts))\r
+    while ((ref >= ip-MAX_DISTANCE) && (nbAttempts))\r
     {\r
         nbAttempts--;\r
         if (*(ref+ml) == *(ip+ml))\r
@@ -423,6 +411,29 @@ forceinline static int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4,
         ref = GETNEXT(ref);\r
     }\r
 \r
+#ifdef REPEAT_OPTIMIZATION\r
+    // Complete table\r
+    if (repl)\r
+    {\r
+        const BYTE* ptr = ip;\r
+        const BYTE* end;\r
+\r
+        end = ip + repl - (MINMATCH-1);\r
+        while(ptr < end-delta)\r
+        {\r
+            DELTANEXT(ptr) = delta;    // Pre-Load\r
+            ptr++;\r
+        }\r
+        do\r
+        {\r
+            DELTANEXT(ptr) = delta;    \r
+            HashTable[HASH_VALUE(ptr)] = (ptr) - base;     // Head of chain\r
+            ptr++;\r
+        } while(ptr < end);\r
+        hc4->nextToUpdate = end;\r
+    }\r
+#endif \r
+\r
     return (int)ml;\r
 }\r
 \r
@@ -440,7 +451,7 @@ forceinline static int LZ4HC_InsertAndGetWiderMatch (LZ4HC_Data_Structure* hc4,
     LZ4HC_Insert(hc4, ip);\r
     ref = HASH_POINTER(ip);\r
 \r
-    while ((ref >= ip-MAX_DISTANCE) && (ref >= hc4->base) && (nbAttempts))\r
+    while ((ref >= ip-MAX_DISTANCE) && (nbAttempts))\r
     {\r
         nbAttempts--;\r
         if (*(startLimit + longest) == *(ref - delta + longest))\r